mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	 f0b9232ad8
			
		
	
	f0b9232ad8
	
	
	
		
			
			Problem Similar to https://github.com/neovim/neovim/pull/33257, but for the date component. When timezone is behind UTC the epoch date of individual components mismatch causing the test to fail. Solution The `epoch` variable is created using `os.date` with a `!`, which means format the date in UTC instead of local timezone: https://www.lua.org/manual/5.1/manual.html#pdf-os.date. Since the individual components like year, month, and day are expected to match `epoch` they should all be created using a `!` as well.
		
			
				
	
	
		
			3642 lines
		
	
	
		
			115 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			3642 lines
		
	
	
		
			115 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local t = require('test.testutil')
 | |
| local n = require('test.functional.testnvim')()
 | |
| local Screen = require('test.functional.ui.screen')
 | |
| local t_shada = require('test.functional.shada.testutil')
 | |
| 
 | |
| local clear = n.clear
 | |
| local eq, api, nvim_eval, nvim_command, exc_exec, fn, nvim_feed =
 | |
|   t.eq, n.api, n.eval, n.command, n.exc_exec, n.fn, n.feed
 | |
| local neq = t.neq
 | |
| local read_file = t.read_file
 | |
| 
 | |
| local get_shada_rw = t_shada.get_shada_rw
 | |
| 
 | |
| local function reset(shada_file)
 | |
|   clear { args = { '-u', 'NORC', '-i', shada_file or 'NONE' } }
 | |
| end
 | |
| 
 | |
| local mpack_eq = function(expected, mpack_result)
 | |
|   local mpack_keys = { 'type', 'timestamp', 'length', 'value' }
 | |
| 
 | |
|   local unpack = vim.mpack.Unpacker()
 | |
|   local actual = {}
 | |
|   local cur, val
 | |
|   local i = 0
 | |
|   local off = 1
 | |
|   while off <= #mpack_result do
 | |
|     val, off = unpack(mpack_result, off)
 | |
|     if i % 4 == 0 then
 | |
|       cur = {}
 | |
|       actual[#actual + 1] = cur
 | |
|     end
 | |
|     local key = mpack_keys[(i % 4) + 1]
 | |
|     if key ~= 'length' then
 | |
|       if key == 'timestamp' and math.abs(val - os.time()) < 2 then
 | |
|         val = 'current'
 | |
|       end
 | |
|       cur[key] = val
 | |
|     end
 | |
|     i = i + 1
 | |
|   end
 | |
|   eq(expected, actual)
 | |
| end
 | |
| 
 | |
| local wshada, _, fname = get_shada_rw('Xtest-functional-plugin-shada.shada')
 | |
| 
 | |
| local wshada_tmp, _, fname_tmp = get_shada_rw('Xtest-functional-plugin-shada.shada.tmp.f')
 | |
| 
 | |
| describe('autoload/shada.vim', function()
 | |
|   local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
 | |
|   setup(function()
 | |
|     reset()
 | |
|     nvim_command([[
 | |
|     function ModifyVal(val)
 | |
|       if type(a:val) == type([])
 | |
|         if len(a:val) == 2 && type(a:val[0]) == type('') && a:val[0][0] is# '!' && has_key(v:msgpack_types, a:val[0][1:])
 | |
|           return {'_TYPE': v:msgpack_types[ a:val[0][1:] ], '_VAL': a:val[1]}
 | |
|         else
 | |
|           return map(copy(a:val), 'ModifyVal(v:val)')
 | |
|         endif
 | |
|       elseif type(a:val) == type({})
 | |
|         let keys = sort(keys(a:val))
 | |
|         let ret = {'_TYPE': v:msgpack_types.map, '_VAL': []}
 | |
|         for key in keys
 | |
|           let k = {'_TYPE': v:msgpack_types.string, '_VAL': split(key, "\n", 1)}
 | |
|           let v = ModifyVal(a:val[key])
 | |
|           call add(ret._VAL, [k, v])
 | |
|           unlet v
 | |
|         endfor
 | |
|         return ret
 | |
|       elseif type(a:val) == type('')
 | |
|         return {'_TYPE': v:msgpack_types.string, '_VAL': split(a:val, "\n", 1)}
 | |
|       else
 | |
|         return a:val
 | |
|       endif
 | |
|     endfunction
 | |
|     ]])
 | |
|   end)
 | |
| 
 | |
|   local sp = function(typ, val)
 | |
|     return ('{"_TYPE": v:msgpack_types.%s, "_VAL": %s}'):format(typ, val)
 | |
|   end
 | |
| 
 | |
|   describe('function shada#mpack_to_sd', function()
 | |
|     local mpack2sd = function(arg)
 | |
|       return ('shada#mpack_to_sd(%s)'):format(arg)
 | |
|     end
 | |
| 
 | |
|     it('works', function()
 | |
|       eq({}, nvim_eval(mpack2sd('[]')))
 | |
|       eq({ { type = 1, timestamp = 5, length = 1, data = 7 } }, nvim_eval(mpack2sd('[1, 5, 1, 7]')))
 | |
|       eq({
 | |
|         { type = 1, timestamp = 5, length = 1, data = 7 },
 | |
|         { type = 1, timestamp = 10, length = 1, data = 5 },
 | |
|       }, nvim_eval(mpack2sd('[1, 5, 1, 7, 1, 10, 1, 5]')))
 | |
|       eq(
 | |
|         'zero-uint:Entry 1 has type element which is zero',
 | |
|         exc_exec('call ' .. mpack2sd('[0, 5, 1, 7]'))
 | |
|       )
 | |
|       eq(
 | |
|         'zero-uint:Entry 1 has type element which is zero',
 | |
|         exc_exec('call ' .. mpack2sd(('[%s, 5, 1, 7]'):format(sp('integer', '[1, 0, 0, 0]'))))
 | |
|       )
 | |
|       eq(
 | |
|         'not-uint:Entry 1 has timestamp element which is not an unsigned integer',
 | |
|         exc_exec('call ' .. mpack2sd('[1, -1, 1, 7]'))
 | |
|       )
 | |
|       eq(
 | |
|         'not-uint:Entry 1 has length element which is not an unsigned integer',
 | |
|         exc_exec('call ' .. mpack2sd('[1, 1, -1, 7]'))
 | |
|       )
 | |
|       eq(
 | |
|         'not-uint:Entry 1 has type element which is not an unsigned integer',
 | |
|         exc_exec('call ' .. mpack2sd('["", 1, -1, 7]'))
 | |
|       )
 | |
|     end)
 | |
|   end)
 | |
| 
 | |
|   describe('function shada#sd_to_strings', function()
 | |
|     local sd2strings_eq = function(expected, arg)
 | |
|       if type(arg) == 'table' then
 | |
|         eq(expected, fn['shada#sd_to_strings'](arg))
 | |
|       else
 | |
|         eq(expected, nvim_eval(('shada#sd_to_strings(%s)'):format(arg)))
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     it('works with empty input', function()
 | |
|       sd2strings_eq({}, '[]')
 | |
|     end)
 | |
| 
 | |
|     it('works with unknown items', function()
 | |
|       sd2strings_eq({
 | |
|         'Unknown (0x64) with timestamp ' .. epoch .. ':',
 | |
|         '  = 100',
 | |
|       }, { { type = 100, timestamp = 0, length = 1, data = 100 } })
 | |
| 
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Unknown (0x4000001180000006) with timestamp ' .. epoch .. ':',
 | |
|           '  = 100',
 | |
|         },
 | |
|         ('[{"type": %s, "timestamp": 0, "length": 1, "data": 100}]'):format(
 | |
|           sp('integer', '[1, 1, 35, 6]')
 | |
|         )
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with multiple unknown items', function()
 | |
|       sd2strings_eq({
 | |
|         'Unknown (0x64) with timestamp ' .. epoch .. ':',
 | |
|         '  = 100',
 | |
|         'Unknown (0x65) with timestamp ' .. epoch .. ':',
 | |
|         '  = 500',
 | |
|       }, {
 | |
|         { type = 100, timestamp = 0, length = 1, data = 100 },
 | |
|         { type = 101, timestamp = 0, length = 1, data = 500 },
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with header items', function()
 | |
|       sd2strings_eq({
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key______  Value',
 | |
|         '  + generator  "test"',
 | |
|       }, { { type = 1, timestamp = 0, data = { generator = 'test' } } })
 | |
|       sd2strings_eq({
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  + a                 1',
 | |
|         '  + b                 2',
 | |
|         '  + c    column       3',
 | |
|         '  + d                 4',
 | |
|       }, { { type = 1, timestamp = 0, data = { a = 1, b = 2, c = 3, d = 4 } } })
 | |
|       sd2strings_eq({
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Value',
 | |
|         '  + t    "test"',
 | |
|       }, { { type = 1, timestamp = 0, data = { t = 'test' } } })
 | |
|       sd2strings_eq({
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: array instead of map',
 | |
|         '  = [1, 2, 3]',
 | |
|       }, { { type = 1, timestamp = 0, data = { 1, 2, 3 } } })
 | |
|     end)
 | |
| 
 | |
|     it('processes standard keys correctly, even in header', function()
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Header with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description________  Value',
 | |
|           '  + c    column               0',
 | |
|           '  + f    file name            "/tmp/foo"',
 | |
|           '  + l    line number          10',
 | |
|           "  + n    name                 '@'",
 | |
|           '  + rc   contents             ["abc", "def"]',
 | |
|           '  + rt   type                 CHARACTERWISE',
 | |
|           '  + ru   is_unnamed           FALSE',
 | |
|           '  + rw   block width          10',
 | |
|           '  + sb   search backward      TRUE',
 | |
|           '  + sc   smartcase value      FALSE',
 | |
|           '  + se   place cursor at end  TRUE',
 | |
|           '  + sh   v:hlsearch value     TRUE',
 | |
|           '  + sl   has line offset      FALSE',
 | |
|           '  + sm   magic value          TRUE',
 | |
|           '  + so   offset value         10',
 | |
|           '  + sp   pattern              "100"',
 | |
|           '  + ss   is :s pattern        TRUE',
 | |
|           '  + su   is last used         FALSE',
 | |
|         },
 | |
|         ([[ [{'type': 1, 'timestamp': 0, 'data': {
 | |
|         'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'so': 10,
 | |
|         'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'sp': '100',
 | |
|         'rt': 0,
 | |
|         'rw': 10,
 | |
|         'rc': ['abc', 'def'],
 | |
|         'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'n': 0x40,
 | |
|         'l': 10,
 | |
|         'c': 0,
 | |
|         'f': '/tmp/foo',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Header with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description____  Value',
 | |
|           '  # Expected integer',
 | |
|           '  + c    column           "abc"',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  + f    file name        "abc\\0def"',
 | |
|           '  # Value is negative',
 | |
|           '  + l    line number      -10',
 | |
|           '  # Value is negative',
 | |
|           '  + n    name             -64',
 | |
|           '  # Expected array value',
 | |
|           '  + rc   contents         "10"',
 | |
|           '  # Unexpected enum value: expected one of '
 | |
|             .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
 | |
|           '  + rt   type             10',
 | |
|           '  # Expected boolean',
 | |
|           '  + ru   is_unnamed       10',
 | |
|           '  # Expected boolean',
 | |
|           '  + sc   smartcase value  NIL',
 | |
|           '  # Expected boolean',
 | |
|           '  + sm   magic value      "TRUE"',
 | |
|           '  # Expected integer',
 | |
|           '  + so   offset value     "TRUE"',
 | |
|           '  + sp   pattern          "abc"',
 | |
|         },
 | |
|         ([[ [{'type': 1, 'timestamp': 0, 'data': {
 | |
|         'sm': 'TRUE',
 | |
|         'sc': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
 | |
|         'so': 'TRUE',
 | |
|         'sp': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]},
 | |
|         'rt': 10,
 | |
|         'rc': '10',
 | |
|         'ru': 10,
 | |
|         'n': -0x40,
 | |
|         'l': -10,
 | |
|         'c': 'abc',
 | |
|         'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Header with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  + f    file name    "abc\\0def"',
 | |
|           '  + rc   contents     ["abc", "abc"]',
 | |
|           '  # Expected integer',
 | |
|           '  + rt   type         "ABC"',
 | |
|         },
 | |
|         ([[ [{'type': 1, 'timestamp': 0, 'data': {
 | |
|         'rt': 'ABC',
 | |
|         'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]}],
 | |
|         'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Header with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  + rc   contents     ["abc", "a\\nd\\0"]',
 | |
|         },
 | |
|         ([[ [{'type': 1, 'timestamp': 0, 'data': {
 | |
|         'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["a", "d\n"]}],
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with search pattern items', function()
 | |
|       sd2strings_eq({
 | |
|         'Search pattern with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: array instead of map',
 | |
|         '  = [1, 2, 3]',
 | |
|       }, { { type = 2, timestamp = 0, data = { 1, 2, 3 } } })
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Search pattern with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description________  Value',
 | |
|           '  + sp   pattern              "abc"',
 | |
|           '  + sh   v:hlsearch value     FALSE',
 | |
|           '  + ss   is :s pattern        FALSE',
 | |
|           '  + sb   search backward      FALSE',
 | |
|           '  + sm   magic value          TRUE',
 | |
|           '  + sc   smartcase value      FALSE',
 | |
|           '  + sl   has line offset      FALSE',
 | |
|           '  + se   place cursor at end  FALSE',
 | |
|           '  + so   offset value         0',
 | |
|           '  + su   is last used         TRUE',
 | |
|         },
 | |
|         ([[ [{'type': 2, 'timestamp': 0, 'data': {
 | |
|         'sp': 'abc',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Search pattern with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description________  Value',
 | |
|           '  + sp   pattern              "abc"',
 | |
|           '  + sh   v:hlsearch value     FALSE',
 | |
|           '  + ss   is :s pattern        FALSE',
 | |
|           '  + sb   search backward      FALSE',
 | |
|           '  + sm   magic value          TRUE',
 | |
|           '  + sc   smartcase value      FALSE',
 | |
|           '  + sl   has line offset      FALSE',
 | |
|           '  + se   place cursor at end  FALSE',
 | |
|           '  + so   offset value         0',
 | |
|           '  + su   is last used         TRUE',
 | |
|           '  + sX                        NIL',
 | |
|           '  + sY                        NIL',
 | |
|           '  + sZ                        NIL',
 | |
|         },
 | |
|         ([[ [{'type': 2, 'timestamp': 0, 'data': {
 | |
|         'sp': 'abc',
 | |
|         'sZ': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
 | |
|         'sY': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
 | |
|         'sX': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Search pattern with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description________  Value',
 | |
|           '  + sp   pattern              "abc"',
 | |
|           '  + sh   v:hlsearch value     FALSE',
 | |
|           '  + ss   is :s pattern        FALSE',
 | |
|           '  + sb   search backward      FALSE',
 | |
|           '  + sm   magic value          TRUE',
 | |
|           '  + sc   smartcase value      FALSE',
 | |
|           '  + sl   has line offset      FALSE',
 | |
|           '  + se   place cursor at end  FALSE',
 | |
|           '  + so   offset value         0',
 | |
|           '  + su   is last used         TRUE',
 | |
|         },
 | |
|         ([[ [{'type': 2, 'timestamp': 0, 'data': {
 | |
|         'sp': 'abc',
 | |
|         'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'so': 0,
 | |
|         'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Search pattern with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description________  Value',
 | |
|           '  # Required key missing: sp',
 | |
|           '  + sh   v:hlsearch value     FALSE',
 | |
|           '  + ss   is :s pattern        FALSE',
 | |
|           '  + sb   search backward      FALSE',
 | |
|           '  + sm   magic value          TRUE',
 | |
|           '  + sc   smartcase value      FALSE',
 | |
|           '  + sl   has line offset      FALSE',
 | |
|           '  + se   place cursor at end  FALSE',
 | |
|           '  + so   offset value         0',
 | |
|           '  + su   is last used         TRUE',
 | |
|         },
 | |
|         ([[ [{'type': 2, 'timestamp': 0, 'data': {
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Search pattern with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description________  Value',
 | |
|           '  + sp   pattern              ""',
 | |
|           '  + sh   v:hlsearch value     TRUE',
 | |
|           '  + ss   is :s pattern        TRUE',
 | |
|           '  + sb   search backward      TRUE',
 | |
|           '  + sm   magic value          FALSE',
 | |
|           '  + sc   smartcase value      TRUE',
 | |
|           '  + sl   has line offset      TRUE',
 | |
|           '  + se   place cursor at end  TRUE',
 | |
|           '  + so   offset value         -10',
 | |
|           '  + su   is last used         FALSE',
 | |
|         },
 | |
|         ([[ [{'type': 2, 'timestamp': 0, 'data': {
 | |
|         'sp': '',
 | |
|         'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|         'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|         'so': -10,
 | |
|         'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Search pattern with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description________  Value',
 | |
|           '  # Expected binary string',
 | |
|           '  + sp   pattern              0',
 | |
|           '  # Expected boolean',
 | |
|           '  + sh   v:hlsearch value     0',
 | |
|           '  # Expected boolean',
 | |
|           '  + ss   is :s pattern        0',
 | |
|           '  # Expected boolean',
 | |
|           '  + sb   search backward      0',
 | |
|           '  # Expected boolean',
 | |
|           '  + sm   magic value          0',
 | |
|           '  # Expected boolean',
 | |
|           '  + sc   smartcase value      0',
 | |
|           '  # Expected boolean',
 | |
|           '  + sl   has line offset      0',
 | |
|           '  # Expected boolean',
 | |
|           '  + se   place cursor at end  0',
 | |
|           '  # Expected integer',
 | |
|           '  + so   offset value         ""',
 | |
|           '  # Expected boolean',
 | |
|           '  + su   is last used         0',
 | |
|         },
 | |
|         ([[ [{'type': 2, 'timestamp': 0, 'data': {
 | |
|         'sp': 0,
 | |
|         'sh': 0,
 | |
|         'ss': 0,
 | |
|         'sb': 0,
 | |
|         'sm': 0,
 | |
|         'sc': 0,
 | |
|         'sl': 0,
 | |
|         'se': 0,
 | |
|         'so': '',
 | |
|         'su': 0,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with replacement string items', function()
 | |
|       sd2strings_eq({
 | |
|         'Replacement string with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: map instead of array',
 | |
|         '  = {"a": [10]}',
 | |
|       }, { { type = 3, timestamp = 0, data = { a = { 10 } } } })
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Replacement string with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description__________  Value',
 | |
|           '  # Expected more elements in list',
 | |
|         },
 | |
|         ([[ [{'type': 3, 'timestamp': 0, 'data': [
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Replacement string with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description__________  Value',
 | |
|           '  # Expected binary string',
 | |
|           '  - :s replacement string  0',
 | |
|         },
 | |
|         ([[ [{'type': 3, 'timestamp': 0, 'data': [
 | |
|         0,
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Replacement string with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description__________  Value',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  - :s replacement string  "abc\\0def"',
 | |
|         },
 | |
|         ([[ [{'type': 3, 'timestamp': 0, 'data': [
 | |
|         {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Replacement string with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description__________  Value',
 | |
|           '  - :s replacement string  "abc\\ndef"',
 | |
|         },
 | |
|         ([[ [{'type': 3, 'timestamp': 0, 'data': [
 | |
|         {'_TYPE': v:msgpack_types.string, '_VAL': ["abc", "def"]},
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Replacement string with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description__________  Value',
 | |
|           '  - :s replacement string  "abc\\ndef"',
 | |
|           '  -                        0',
 | |
|         },
 | |
|         ([[ [{'type': 3, 'timestamp': 0, 'data': [
 | |
|         {'_TYPE': v:msgpack_types.string, '_VAL': ["abc", "def"]},
 | |
|         0,
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with history entry items', function()
 | |
|       sd2strings_eq({
 | |
|         'History entry with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: map instead of array',
 | |
|         '  = {"a": [10]}',
 | |
|       }, { { type = 4, timestamp = 0, data = { a = { 10 } } } })
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  # Expected more elements in list',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  # Expected integer',
 | |
|           '  - history type  ""',
 | |
|           '  # Expected more elements in list',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         '',
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
 | |
|             .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
 | |
|           '  - history type  5',
 | |
|           '  - contents      ""',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         5,
 | |
|         ''
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
 | |
|             .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
 | |
|           '  - history type  5',
 | |
|           '  - contents      ""',
 | |
|           '  -               32',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         5,
 | |
|         '',
 | |
|         0x20
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  CMD',
 | |
|           '  - contents      ""',
 | |
|           '  -               32',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         0,
 | |
|         '',
 | |
|         0x20
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  SEARCH',
 | |
|           '  - contents      ""',
 | |
|           "  - separator     ' '",
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         1,
 | |
|         '',
 | |
|         0x20
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  SEARCH',
 | |
|           '  - contents      ""',
 | |
|           '  # Expected more elements in list',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         1,
 | |
|         '',
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  EXPR',
 | |
|           '  - contents      ""',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         2,
 | |
|         '',
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  INPUT',
 | |
|           '  - contents      ""',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         3,
 | |
|         '',
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  DEBUG',
 | |
|           '  - contents      ""',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         4,
 | |
|         '',
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  DEBUG',
 | |
|           '  # Expected binary string',
 | |
|           '  - contents      10',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         4,
 | |
|         10,
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  DEBUG',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  - contents      "abc\\0def"',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         4,
 | |
|         {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  SEARCH',
 | |
|           '  - contents      "abc"',
 | |
|           '  # Expected integer',
 | |
|           '  - separator     ""',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         1,
 | |
|         'abc',
 | |
|         '',
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  SEARCH',
 | |
|           '  - contents      "abc"',
 | |
|           '  # Value is negative',
 | |
|           '  - separator     -1',
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         1,
 | |
|         'abc',
 | |
|         -1,
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       -- Regression: NUL separator must be properly supported
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  SEARCH',
 | |
|           '  - contents      ""',
 | |
|           "  - separator     '\\0'",
 | |
|         },
 | |
|         ([[ [{'type': 4, 'timestamp': 0, 'data': [
 | |
|         1,
 | |
|         '',
 | |
|         0x0
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with register items', function()
 | |
|       sd2strings_eq({
 | |
|         'Register with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: array instead of map',
 | |
|         '  = [1, 2, 3]',
 | |
|       }, { { type = 5, timestamp = 0, data = { 1, 2, 3 } } })
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Register with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: n',
 | |
|           '  # Required key missing: rc',
 | |
|           '  + rw   block width  0',
 | |
|           '  + rt   type         CHARACTERWISE',
 | |
|           '  + ru   is_unnamed   FALSE',
 | |
|         },
 | |
|         ([[ [{'type': 5, 'timestamp': 0, 'data': {
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Register with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           "  + n    name         ' '",
 | |
|           '  # Required key missing: rc',
 | |
|           '  + rw   block width  0',
 | |
|           '  + rt   type         CHARACTERWISE',
 | |
|           '  + ru   is_unnamed   FALSE',
 | |
|         },
 | |
|         ([[ [{'type': 5, 'timestamp': 0, 'data': {
 | |
|         'n': 0x20,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Register with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           "  + n    name         ' '",
 | |
|           '  + rc   contents     ["abc", "def"]',
 | |
|           '  + rw   block width  0',
 | |
|           '  + rt   type         CHARACTERWISE',
 | |
|           '  + ru   is_unnamed   FALSE',
 | |
|         },
 | |
|         ([[ [{'type': 5, 'timestamp': 0, 'data': {
 | |
|         'n': 0x20,
 | |
|         'rc': ["abc", "def"],
 | |
|         'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Register with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           "  + n    name         ' '",
 | |
|           '  + rc   contents     @',
 | |
|           '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|           '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|           '  + rw   block width  0',
 | |
|           '  + rt   type         CHARACTERWISE',
 | |
|           '  + ru   is_unnamed   TRUE',
 | |
|         },
 | |
|         ([[ [{'type': 5, 'timestamp': 0, 'data': {
 | |
|         'n': 0x20,
 | |
|         'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
 | |
|         'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Register with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           "  + n    name         ' '",
 | |
|           '  + rc   contents     @',
 | |
|           '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|           '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|           '  + rw   block width  0',
 | |
|           '  + rt   type         CHARACTERWISE',
 | |
|           '  + ru   is_unnamed   FALSE',
 | |
|         },
 | |
|         ([[ [{'type': 5, 'timestamp': 0, 'data': {
 | |
|         'n': 0x20,
 | |
|         'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
 | |
|         'rw': 0,
 | |
|         'rt': 0,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Register with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           "  + n    name         ' '",
 | |
|           '  + rc   contents     @',
 | |
|           '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|           '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|           '  + rw   block width  5',
 | |
|           '  + rt   type         LINEWISE',
 | |
|           '  + ru   is_unnamed   FALSE',
 | |
|         },
 | |
|         ([[ [{'type': 5, 'timestamp': 0, 'data': {
 | |
|         'n': 0x20,
 | |
|         'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
 | |
|         'rw': 5,
 | |
|         'rt': 1,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Register with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           "  + n    name         ' '",
 | |
|           '  + rc   contents     @',
 | |
|           '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|           '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|           '  # Expected integer',
 | |
|           '  + rw   block width  ""',
 | |
|           '  + rt   type         BLOCKWISE',
 | |
|           '  # Expected boolean',
 | |
|           '  + ru   is_unnamed   ""',
 | |
|         },
 | |
|         ([[ [{'type': 5, 'timestamp': 0, 'data': {
 | |
|         'n': 0x20,
 | |
|         'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
 | |
|         'rw': "",
 | |
|         'rt': 2,
 | |
|         'ru': ""
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Register with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           "  + n    name         ' '",
 | |
|           '  # Expected array value',
 | |
|           '  + rc   contents     0',
 | |
|           '  # Value is negative',
 | |
|           '  + rw   block width  -1',
 | |
|           '  # Unexpected enum value: expected one of 0 (CHARACTERWISE), '
 | |
|             .. '1 (LINEWISE), 2 (BLOCKWISE)',
 | |
|           '  + rt   type         10',
 | |
|           '  # Expected boolean',
 | |
|           '  + ru   is_unnamed   ["abc", "def"]',
 | |
|         },
 | |
|         ([[ [{'type': 5, 'timestamp': 0, 'data': {
 | |
|         'n': 0x20,
 | |
|         'rc': 0,
 | |
|         'rw': -1,
 | |
|         'rt': 10,
 | |
|         'ru': ['abc', 'def'],
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Register with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           "  + n    name         ' '",
 | |
|           '  + rc   contents     @',
 | |
|           '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|           '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|           '  + rw   block width  5',
 | |
|           '  + rt   type         LINEWISE',
 | |
|           '  # Expected boolean',
 | |
|           '  + ru   is_unnamed   0',
 | |
|         },
 | |
|         ([[ [{'type': 5, 'timestamp': 0, 'data': {
 | |
|         'n': 0x20,
 | |
|         'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
 | |
|         'rw': 5,
 | |
|         'rt': 1,
 | |
|         'ru': 0,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with variable items', function()
 | |
|       sd2strings_eq({
 | |
|         'Variable with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: map instead of array',
 | |
|         '  = {"a": [10]}',
 | |
|       }, { { type = 6, timestamp = 0, data = { a = { 10 } } } })
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Variable with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description  Value',
 | |
|           '  # Expected more elements in list',
 | |
|         },
 | |
|         ([[ [{'type': 6, 'timestamp': 0, 'data': [
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Variable with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description  Value',
 | |
|           '  # Expected binary string',
 | |
|           '  - name         1',
 | |
|           '  # Expected more elements in list',
 | |
|         },
 | |
|         ([[ [{'type': 6, 'timestamp': 0, 'data': [
 | |
|         1
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Variable with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description  Value',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  - name         "\\0"',
 | |
|           '  # Expected more elements in list',
 | |
|         },
 | |
|         ([[ [{'type': 6, 'timestamp': 0, 'data': [
 | |
|         {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Variable with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description  Value',
 | |
|           '  - name         "foo"',
 | |
|           '  # Expected more elements in list',
 | |
|         },
 | |
|         ([[ [{'type': 6, 'timestamp': 0, 'data': [
 | |
|         {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]},
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Variable with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description  Value',
 | |
|           '  - name         "foo"',
 | |
|           '  - value        NIL',
 | |
|         },
 | |
|         ([[ [{'type': 6, 'timestamp': 0, 'data': [
 | |
|         {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]},
 | |
|         {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Variable with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description  Value',
 | |
|           '  - name         "foo"',
 | |
|           '  - value        NIL',
 | |
|           '  -              NIL',
 | |
|         },
 | |
|         ([[ [{'type': 6, 'timestamp': 0, 'data': [
 | |
|         {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]},
 | |
|         {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
 | |
|         {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with global mark items', function()
 | |
|       sd2strings_eq({
 | |
|         'Global mark with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: array instead of map',
 | |
|         '  = [1, 2, 3]',
 | |
|       }, { { type = 7, timestamp = 0, data = { 1, 2, 3 } } })
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Global mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: n',
 | |
|           '  # Required key missing: f',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 7, 'timestamp': 0, 'data': {
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Global mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Expected integer',
 | |
|           '  + n    name         "foo"',
 | |
|           '  # Required key missing: f',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 7, 'timestamp': 0, 'data': {
 | |
|         'n': 'foo',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Global mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: n',
 | |
|           '  + f    file name    "foo"',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 7, 'timestamp': 0, 'data': {
 | |
|         'f': 'foo',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Global mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Value is negative',
 | |
|           '  + n    name         -10',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  + f    file name    "\\0"',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 7, 'timestamp': 0, 'data': {
 | |
|         'n': -10,
 | |
|         'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Global mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           "  + n    name         '\\20'",
 | |
|           '  + f    file name    "foo"',
 | |
|           '  # Value is negative',
 | |
|           '  + l    line number  -10',
 | |
|           '  # Value is negative',
 | |
|           '  + c    column       -10',
 | |
|         },
 | |
|         ([[ [{'type': 7, 'timestamp': 0, 'data': {
 | |
|         'n': 20,
 | |
|         'f': 'foo',
 | |
|         'l': -10,
 | |
|         'c': -10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Global mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  + n    name         128',
 | |
|           '  + f    file name    "foo"',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 7, 'timestamp': 0, 'data': {
 | |
|         'n': 128,
 | |
|         'f': 'foo',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Global mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           "  + n    name         '\\20'",
 | |
|           '  + f    file name    "foo"',
 | |
|           '  # Expected integer',
 | |
|           '  + l    line number  "FOO"',
 | |
|           '  # Expected integer',
 | |
|           '  + c    column       "foo"',
 | |
|           '  + mX                10',
 | |
|         },
 | |
|         ([[ [{'type': 7, 'timestamp': 0, 'data': {
 | |
|         'n': 20,
 | |
|         'f': 'foo',
 | |
|         'l': 'FOO',
 | |
|         'c': 'foo',
 | |
|         'mX': 10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Global mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key________  Description  Value',
 | |
|           "  + n            name         'A'",
 | |
|           '  + f            file name    "foo"',
 | |
|           '  + l            line number  2',
 | |
|           '  + c            column       200',
 | |
|           '  + mX                        10',
 | |
|           '  + mYYYYYYYYYY               10',
 | |
|         },
 | |
|         ([[ [{'type': 7, 'timestamp': 0, 'data': {
 | |
|         'n': char2nr('A'),
 | |
|         'f': 'foo',
 | |
|         'l': 2,
 | |
|         'c': 200,
 | |
|         'mX': 10,
 | |
|         'mYYYYYYYYYY': 10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with jump items', function()
 | |
|       sd2strings_eq({
 | |
|         'Jump with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: array instead of map',
 | |
|         '  = [1, 2, 3]',
 | |
|       }, { { type = 8, timestamp = 0, data = { 1, 2, 3 } } })
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Jump with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: f',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 8, 'timestamp': 0, 'data': {
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Jump with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: f',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|           '  # Expected integer',
 | |
|           '  + n    name         "foo"',
 | |
|         },
 | |
|         ([[ [{'type': 8, 'timestamp': 0, 'data': {
 | |
|         'n': 'foo',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Jump with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  + f    file name    "foo"',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 8, 'timestamp': 0, 'data': {
 | |
|         'f': 'foo',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Jump with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  + f    file name    "\\0"',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|           '  # Value is negative',
 | |
|           '  + n    name         -10',
 | |
|         },
 | |
|         ([[ [{'type': 8, 'timestamp': 0, 'data': {
 | |
|         'n': -10,
 | |
|         'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Jump with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  + f    file name    "foo"',
 | |
|           '  # Value is negative',
 | |
|           '  + l    line number  -10',
 | |
|           '  # Value is negative',
 | |
|           '  + c    column       -10',
 | |
|         },
 | |
|         ([[ [{'type': 8, 'timestamp': 0, 'data': {
 | |
|         'f': 'foo',
 | |
|         'l': -10,
 | |
|         'c': -10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Jump with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  + f    file name    "foo"',
 | |
|           '  # Expected integer',
 | |
|           '  + l    line number  "FOO"',
 | |
|           '  # Expected integer',
 | |
|           '  + c    column       "foo"',
 | |
|           '  + mX                10',
 | |
|         },
 | |
|         ([[ [{'type': 8, 'timestamp': 0, 'data': {
 | |
|         'f': 'foo',
 | |
|         'l': 'FOO',
 | |
|         'c': 'foo',
 | |
|         'mX': 10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Jump with timestamp ' .. epoch .. ':',
 | |
|           '  % Key________  Description  Value',
 | |
|           '  + f            file name    "foo"',
 | |
|           '  + l            line number  2',
 | |
|           '  + c            column       200',
 | |
|           '  + mX                        10',
 | |
|           '  + mYYYYYYYYYY               10',
 | |
|           "  + n            name         ' '",
 | |
|         },
 | |
|         ([[ [{'type': 8, 'timestamp': 0, 'data': {
 | |
|         'n': 0x20,
 | |
|         'f': 'foo',
 | |
|         'l': 2,
 | |
|         'c': 200,
 | |
|         'mX': 10,
 | |
|         'mYYYYYYYYYY': 10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with buffer list items', function()
 | |
|       sd2strings_eq({
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: map instead of array',
 | |
|         '  = {"a": [10]}',
 | |
|       }, { { type = 9, timestamp = 0, data = { a = { 10 } } } })
 | |
|       sd2strings_eq({
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  # Expected array of maps',
 | |
|         '  = [[], []]',
 | |
|       }, { { type = 9, timestamp = 0, data = { {}, {} } } })
 | |
|       sd2strings_eq({
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  # Expected array of maps',
 | |
|         '  = [{"a": 10}, []]',
 | |
|       }, { { type = 9, timestamp = 0, data = { { a = 10 }, {} } } })
 | |
|       sd2strings_eq({
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Required key missing: f',
 | |
|         '  + l    line number  1',
 | |
|         '  + c    column       0',
 | |
|         '  + a                 10',
 | |
|       }, { { type = 9, timestamp = 0, data = { { a = 10 } } } })
 | |
|       sd2strings_eq({
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Required key missing: f',
 | |
|         '  # Expected integer',
 | |
|         '  + l    line number  "10"',
 | |
|         '  # Expected integer',
 | |
|         '  + c    column       "10"',
 | |
|         '  + a                 10',
 | |
|       }, { { type = 9, timestamp = 0, data = { { l = '10', c = '10', a = 10 } } } })
 | |
|       sd2strings_eq({
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Required key missing: f',
 | |
|         '  + l    line number  10',
 | |
|         '  + c    column       10',
 | |
|         '  + a                 10',
 | |
|       }, { { type = 9, timestamp = 0, data = { { l = 10, c = 10, a = 10 } } } })
 | |
|       sd2strings_eq({
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Required key missing: f',
 | |
|         '  # Value is negative',
 | |
|         '  + l    line number  -10',
 | |
|         '  # Value is negative',
 | |
|         '  + c    column       -10',
 | |
|       }, { { type = 9, timestamp = 0, data = { { l = -10, c = -10 } } } })
 | |
|       sd2strings_eq({
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  + f    file name    "abc"',
 | |
|         '  + l    line number  1',
 | |
|         '  + c    column       0',
 | |
|       }, { { type = 9, timestamp = 0, data = { { f = 'abc' } } } })
 | |
|       sd2strings_eq({
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Expected binary string',
 | |
|         '  + f    file name    10',
 | |
|         '  + l    line number  1',
 | |
|         '  + c    column       0',
 | |
|         '',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Expected binary string',
 | |
|         '  + f    file name    20',
 | |
|         '  + l    line number  1',
 | |
|         '  + c    column       0',
 | |
|       }, { { type = 9, timestamp = 0, data = { { f = 10 }, { f = 20 } } } })
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Buffer list with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Expected binary string',
 | |
|           '  + f    file name    10',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|           '',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  + f    file name    "\\0"',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 9, 'timestamp': 0, 'data': [
 | |
|         {'f': 10},
 | |
|         {'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]}},
 | |
|       ]}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with local mark items', function()
 | |
|       sd2strings_eq({
 | |
|         'Local mark with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: array instead of map',
 | |
|         '  = [1, 2, 3]',
 | |
|       }, { { type = 10, timestamp = 0, data = { 1, 2, 3 } } })
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Local mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: f',
 | |
|           "  + n    name         '\"'",
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 10, 'timestamp': 0, 'data': {
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Local mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: f',
 | |
|           '  # Expected integer',
 | |
|           '  + n    name         "foo"',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 10, 'timestamp': 0, 'data': {
 | |
|         'n': 'foo',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Local mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  + f    file name    "foo"',
 | |
|           "  + n    name         '\"'",
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 10, 'timestamp': 0, 'data': {
 | |
|         'f': 'foo',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Local mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  + f    file name    "\\0"',
 | |
|           '  # Value is negative',
 | |
|           '  + n    name         -10',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 10, 'timestamp': 0, 'data': {
 | |
|         'n': -10,
 | |
|         'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Local mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  + f    file name    "foo"',
 | |
|           "  + n    name         '\\20'",
 | |
|           '  # Value is negative',
 | |
|           '  + l    line number  -10',
 | |
|           '  # Value is negative',
 | |
|           '  + c    column       -10',
 | |
|         },
 | |
|         ([[ [{'type': 10, 'timestamp': 0, 'data': {
 | |
|         'n': 20,
 | |
|         'f': 'foo',
 | |
|         'l': -10,
 | |
|         'c': -10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Local mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  + f    file name    "foo"',
 | |
|           "  + n    name         '\\20'",
 | |
|           '  # Expected integer',
 | |
|           '  + l    line number  "FOO"',
 | |
|           '  # Expected integer',
 | |
|           '  + c    column       "foo"',
 | |
|           '  + mX                10',
 | |
|         },
 | |
|         ([[ [{'type': 10, 'timestamp': 0, 'data': {
 | |
|         'n': 20,
 | |
|         'f': 'foo',
 | |
|         'l': 'FOO',
 | |
|         'c': 'foo',
 | |
|         'mX': 10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Local mark with timestamp ' .. epoch .. ':',
 | |
|           '  % Key________  Description  Value',
 | |
|           '  + f            file name    "foo"',
 | |
|           "  + n            name         'a'",
 | |
|           '  + l            line number  2',
 | |
|           '  + c            column       200',
 | |
|           '  + mX                        10',
 | |
|           '  + mYYYYYYYYYY               10',
 | |
|         },
 | |
|         ([[ [{'type': 10, 'timestamp': 0, 'data': {
 | |
|         'n': char2nr('a'),
 | |
|         'f': 'foo',
 | |
|         'l': 2,
 | |
|         'c': 200,
 | |
|         'mX': 10,
 | |
|         'mYYYYYYYYYY': 10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
| 
 | |
|     it('works with change items', function()
 | |
|       sd2strings_eq({
 | |
|         'Change with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: array instead of map',
 | |
|         '  = [1, 2, 3]',
 | |
|       }, { { type = 11, timestamp = 0, data = { 1, 2, 3 } } })
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Change with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: f',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 11, 'timestamp': 0, 'data': {
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Change with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: f',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|           '  # Expected integer',
 | |
|           '  + n    name         "foo"',
 | |
|         },
 | |
|         ([[ [{'type': 11, 'timestamp': 0, 'data': {
 | |
|         'n': 'foo',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Change with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  + f    file name    "foo"',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|         },
 | |
|         ([[ [{'type': 11, 'timestamp': 0, 'data': {
 | |
|         'f': 'foo',
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Change with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Expected no NUL bytes',
 | |
|           '  + f    file name    "\\0"',
 | |
|           '  + l    line number  1',
 | |
|           '  + c    column       0',
 | |
|           '  # Value is negative',
 | |
|           '  + n    name         -10',
 | |
|         },
 | |
|         ([[ [{'type': 11, 'timestamp': 0, 'data': {
 | |
|         'n': -10,
 | |
|         'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Change with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  + f    file name    "foo"',
 | |
|           '  # Value is negative',
 | |
|           '  + l    line number  -10',
 | |
|           '  # Value is negative',
 | |
|           '  + c    column       -10',
 | |
|         },
 | |
|         ([[ [{'type': 11, 'timestamp': 0, 'data': {
 | |
|         'f': 'foo',
 | |
|         'l': -10,
 | |
|         'c': -10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Change with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  + f    file name    "foo"',
 | |
|           '  # Expected integer',
 | |
|           '  + l    line number  "FOO"',
 | |
|           '  # Expected integer',
 | |
|           '  + c    column       "foo"',
 | |
|           '  + mX                10',
 | |
|         },
 | |
|         ([[ [{'type': 11, 'timestamp': 0, 'data': {
 | |
|         'f': 'foo',
 | |
|         'l': 'FOO',
 | |
|         'c': 'foo',
 | |
|         'mX': 10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|       sd2strings_eq(
 | |
|         {
 | |
|           'Change with timestamp ' .. epoch .. ':',
 | |
|           '  % Key________  Description  Value',
 | |
|           '  + f            file name    "foo"',
 | |
|           '  + l            line number  2',
 | |
|           '  + c            column       200',
 | |
|           '  + mX                        10',
 | |
|           '  + mYYYYYYYYYY               10',
 | |
|           "  + n            name         ' '",
 | |
|         },
 | |
|         ([[ [{'type': 11, 'timestamp': 0, 'data': {
 | |
|         'n': 0x20,
 | |
|         'f': 'foo',
 | |
|         'l': 2,
 | |
|         'c': 200,
 | |
|         'mX': 10,
 | |
|         'mYYYYYYYYYY': 10,
 | |
|       }}] ]]):gsub('\n', '')
 | |
|       )
 | |
|     end)
 | |
|   end)
 | |
| 
 | |
|   describe('function shada#get_strings', function()
 | |
|     it('works', function()
 | |
|       eq({
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Value',
 | |
|       }, nvim_eval('shada#get_strings(msgpackdump([1, 0, 0, {}]))'))
 | |
|     end)
 | |
|   end)
 | |
| 
 | |
|   describe('function shada#strings_to_sd', function()
 | |
|     local strings2sd_eq = function(expected, input)
 | |
|       api.nvim_set_var('__input', input)
 | |
|       nvim_command(
 | |
|         'let g:__actual = map(shada#strings_to_sd(g:__input), '
 | |
|           .. '"filter(v:val, \\"v:key[0] isnot# \'_\' '
 | |
|           .. '&& v:key isnot# \'length\'\\")")'
 | |
|       )
 | |
|       -- print()
 | |
|       if type(expected) == 'table' then
 | |
|         api.nvim_set_var('__expected', expected)
 | |
|         nvim_command('let g:__expected = ModifyVal(g:__expected)')
 | |
|         expected = 'g:__expected'
 | |
|         -- print(nvim_eval('msgpack#string(g:__expected)'))
 | |
|       end
 | |
|       -- print(nvim_eval('msgpack#string(g:__actual)'))
 | |
|       eq(1, nvim_eval(('msgpack#equal(%s, g:__actual)'):format(expected)))
 | |
|       if type(expected) == 'table' then
 | |
|         nvim_command('unlet g:__expected')
 | |
|       end
 | |
|       nvim_command('unlet g:__input')
 | |
|       nvim_command('unlet g:__actual')
 | |
|     end
 | |
| 
 | |
|     it('works with multiple items', function()
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 11,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             f = 'foo',
 | |
|             l = 2,
 | |
|             c = 200,
 | |
|             mX = 10,
 | |
|             mYYYYYYYYYY = 10,
 | |
|             n = (' '):byte(),
 | |
|           },
 | |
|         },
 | |
|         {
 | |
|           type = 1,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             c = 'abc',
 | |
|             f = { '!string', { 'abc\ndef' } },
 | |
|             l = -10,
 | |
|             n = -64,
 | |
|             rc = '10',
 | |
|             rt = 10,
 | |
|             sc = { '!nil', 0 },
 | |
|             sm = 'TRUE',
 | |
|             so = 'TRUE',
 | |
|             sp = { '!string', { 'abc' } },
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Change with timestamp ' .. epoch .. ':',
 | |
|         '  % Key________  Description  Value',
 | |
|         '  + f            file name    "foo"',
 | |
|         '  + l            line number  2',
 | |
|         '  + c            column       200',
 | |
|         '  + mX                        10',
 | |
|         '  + mYYYYYYYYYY               10',
 | |
|         "  + n            name         ' '",
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description____  Value',
 | |
|         '  # Expected integer',
 | |
|         '  + c    column           "abc"',
 | |
|         '  # Expected no NUL bytes',
 | |
|         '  + f    file name        "abc\\0def"',
 | |
|         '  # Value is negative',
 | |
|         '  + l    line number      -10',
 | |
|         '  # Value is negative',
 | |
|         '  + n    name             -64',
 | |
|         '  # Expected array value',
 | |
|         '  + rc   contents         "10"',
 | |
|         '  # Unexpected enum value: expected one of '
 | |
|           .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
 | |
|         '  + rt   type             10',
 | |
|         '  # Expected boolean',
 | |
|         '  + sc   smartcase value  NIL',
 | |
|         '  # Expected boolean',
 | |
|         '  + sm   magic value      "TRUE"',
 | |
|         '  # Expected integer',
 | |
|         '  + so   offset value     "TRUE"',
 | |
|         '  # Expected binary string',
 | |
|         '  + sp   pattern          ="abc"',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with empty list', function()
 | |
|       strings2sd_eq({}, {})
 | |
|     end)
 | |
| 
 | |
|     it('works with header items', function()
 | |
|       strings2sd_eq({ { type = 1, timestamp = 0, data = {
 | |
|         generator = 'test',
 | |
|       } } }, {
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key______  Value',
 | |
|         '  + generator  "test"',
 | |
|       })
 | |
|       strings2sd_eq(
 | |
|         { { type = 1, timestamp = 0, data = {
 | |
|           1,
 | |
|           2,
 | |
|           3,
 | |
|         } } },
 | |
|         {
 | |
|           'Header with timestamp ' .. epoch .. ':',
 | |
|           '  # Unexpected type: array instead of map',
 | |
|           '  = [1, 2, 3]',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 1,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             a = 1,
 | |
|             b = 2,
 | |
|             c = 3,
 | |
|             d = 4,
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  + a                 1',
 | |
|         '  + b                 2',
 | |
|         '  + c    column       3',
 | |
|         '  + d                 4',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 1,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             c = 'abc',
 | |
|             f = { '!string', { 'abc\ndef' } },
 | |
|             l = -10,
 | |
|             n = -64,
 | |
|             rc = '10',
 | |
|             rt = 10,
 | |
|             sc = { '!nil', 0 },
 | |
|             sm = 'TRUE',
 | |
|             so = 'TRUE',
 | |
|             sp = { '!string', { 'abc' } },
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description____  Value',
 | |
|         '  # Expected integer',
 | |
|         '  + c    column           "abc"',
 | |
|         '  # Expected no NUL bytes',
 | |
|         '  + f    file name        "abc\\0def"',
 | |
|         '  # Value is negative',
 | |
|         '  + l    line number      -10',
 | |
|         '  # Value is negative',
 | |
|         '  + n    name             -64',
 | |
|         '  # Expected array value',
 | |
|         '  + rc   contents         "10"',
 | |
|         '  # Unexpected enum value: expected one of '
 | |
|           .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
 | |
|         '  + rt   type             10',
 | |
|         '  # Expected boolean',
 | |
|         '  + sc   smartcase value  NIL',
 | |
|         '  # Expected boolean',
 | |
|         '  + sm   magic value      "TRUE"',
 | |
|         '  # Expected integer',
 | |
|         '  + so   offset value     "TRUE"',
 | |
|         '  # Expected binary string',
 | |
|         '  + sp   pattern          ="abc"',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with search pattern items', function()
 | |
|       strings2sd_eq(
 | |
|         { { type = 2, timestamp = 0, data = {
 | |
|           1,
 | |
|           2,
 | |
|           3,
 | |
|         } } },
 | |
|         {
 | |
|           'Search pattern with timestamp ' .. epoch .. ':',
 | |
|           '  # Unexpected type: array instead of map',
 | |
|           '  = [1, 2, 3]',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({ { type = 2, timestamp = 0, data = {
 | |
|         sp = 'abc',
 | |
|       } } }, {
 | |
|         'Search pattern with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description________  Value',
 | |
|         '  + sp   pattern              "abc"',
 | |
|         '  + sh   v:hlsearch value     FALSE',
 | |
|         '  + ss   is :s pattern        FALSE',
 | |
|         '  + sm   magic value          TRUE',
 | |
|         '  + sc   smartcase value      FALSE',
 | |
|         '  + sl   has line offset      FALSE',
 | |
|         '  + se   place cursor at end  FALSE',
 | |
|         '  + so   offset value         0',
 | |
|         '  + su   is last used         TRUE',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 2,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             sp = 'abc',
 | |
|             sX = { '!nil', 0 },
 | |
|             sY = { '!nil', 0 },
 | |
|             sZ = { '!nil', 0 },
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Search pattern with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description________  Value',
 | |
|         '  + sp   pattern              "abc"',
 | |
|         '  + sh   v:hlsearch value     FALSE',
 | |
|         '  + ss   is :s pattern        FALSE',
 | |
|         '  + sm   magic value          TRUE',
 | |
|         '  + sc   smartcase value      FALSE',
 | |
|         '  + sl   has line offset      FALSE',
 | |
|         '  + se   place cursor at end  FALSE',
 | |
|         '  + so   offset value         0',
 | |
|         '  + su   is last used         TRUE',
 | |
|         '  + sX                        NIL',
 | |
|         '  + sY                        NIL',
 | |
|         '  + sZ                        NIL',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 2, timestamp = 0, data = { '!map', {} } } }, {
 | |
|         'Search pattern with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description________  Value',
 | |
|         '  # Required key missing: sp',
 | |
|         '  + sh   v:hlsearch value     FALSE',
 | |
|         '  + ss   is :s pattern        FALSE',
 | |
|         '  + sm   magic value          TRUE',
 | |
|         '  + sc   smartcase value      FALSE',
 | |
|         '  + sl   has line offset      FALSE',
 | |
|         '  + se   place cursor at end  FALSE',
 | |
|         '  + so   offset value         0',
 | |
|         '  + su   is last used         TRUE',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 2,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             sp = '',
 | |
|             sh = { '!boolean', 1 },
 | |
|             ss = { '!boolean', 1 },
 | |
|             sc = { '!boolean', 1 },
 | |
|             sl = { '!boolean', 1 },
 | |
|             se = { '!boolean', 1 },
 | |
|             sm = { '!boolean', 0 },
 | |
|             su = { '!boolean', 0 },
 | |
|             so = -10,
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Search pattern with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description________  Value',
 | |
|         '  + sp   pattern              ""',
 | |
|         '  + sh   v:hlsearch value     TRUE',
 | |
|         '  + ss   is :s pattern        TRUE',
 | |
|         '  + sm   magic value          FALSE',
 | |
|         '  + sc   smartcase value      TRUE',
 | |
|         '  + sl   has line offset      TRUE',
 | |
|         '  + se   place cursor at end  TRUE',
 | |
|         '  + so   offset value         -10',
 | |
|         '  + su   is last used         FALSE',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 2,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             sp = 0,
 | |
|             sh = 0,
 | |
|             ss = 0,
 | |
|             sc = 0,
 | |
|             sl = 0,
 | |
|             se = 0,
 | |
|             sm = 0,
 | |
|             su = 0,
 | |
|             so = '',
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Search pattern with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description________  Value',
 | |
|         '  # Expected binary string',
 | |
|         '  + sp   pattern              0',
 | |
|         '  # Expected boolean',
 | |
|         '  + sh   v:hlsearch value     0',
 | |
|         '  # Expected boolean',
 | |
|         '  + ss   is :s pattern        0',
 | |
|         '  # Expected boolean',
 | |
|         '  + sm   magic value          0',
 | |
|         '  # Expected boolean',
 | |
|         '  + sc   smartcase value      0',
 | |
|         '  # Expected boolean',
 | |
|         '  + sl   has line offset      0',
 | |
|         '  # Expected boolean',
 | |
|         '  + se   place cursor at end  0',
 | |
|         '  # Expected integer',
 | |
|         '  + so   offset value         ""',
 | |
|         '  # Expected boolean',
 | |
|         '  + su   is last used         0',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with replacement string items', function()
 | |
|       strings2sd_eq({ { type = 3, timestamp = 0, data = {
 | |
|         a = { 10 },
 | |
|       } } }, {
 | |
|         'Replacement string with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: map instead of array',
 | |
|         '  = {"a": [10]}',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 3, timestamp = 0, data = {} } }, {
 | |
|         'Replacement string with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description__________  Value',
 | |
|         '  # Expected more elements in list',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 3, timestamp = 0, data = {
 | |
|         0,
 | |
|       } } }, {
 | |
|         'Replacement string with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description__________  Value',
 | |
|         '  # Expected binary string',
 | |
|         '  - :s replacement string  0',
 | |
|       })
 | |
|       strings2sd_eq(
 | |
|         { { type = 3, timestamp = 0, data = {
 | |
|           'abc\ndef',
 | |
|           0,
 | |
|         } } },
 | |
|         {
 | |
|           'Replacement string with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description__________  Value',
 | |
|           '  - :s replacement string  "abc\\ndef"',
 | |
|           '  -                        0',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({ { type = 3, timestamp = 0, data = {
 | |
|         'abc\ndef',
 | |
|       } } }, {
 | |
|         'Replacement string with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description__________  Value',
 | |
|         '  - :s replacement string  "abc\\ndef"',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with history entry items', function()
 | |
|       strings2sd_eq({ { type = 4, timestamp = 0, data = {
 | |
|         a = { 10 },
 | |
|       } } }, {
 | |
|         'History entry with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: map instead of array',
 | |
|         '  = {"a": [10]}',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 4, timestamp = 0, data = {} } }, {
 | |
|         'History entry with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description_  Value',
 | |
|         '  # Expected more elements in list',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 4, timestamp = 0, data = {
 | |
|         '',
 | |
|       } } }, {
 | |
|         'History entry with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description_  Value',
 | |
|         '  # Expected integer',
 | |
|         '  - history type  ""',
 | |
|         '  # Expected more elements in list',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 4, timestamp = 0, data = {
 | |
|         5,
 | |
|         '',
 | |
|       } } }, {
 | |
|         'History entry with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description_  Value',
 | |
|         '  # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
 | |
|           .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
 | |
|         '  - history type  5',
 | |
|         '  - contents      ""',
 | |
|       })
 | |
|       strings2sd_eq(
 | |
|         { { type = 4, timestamp = 0, data = {
 | |
|           5,
 | |
|           '',
 | |
|           32,
 | |
|         } } },
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
 | |
|             .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
 | |
|           '  - history type  5',
 | |
|           '  - contents      ""',
 | |
|           '  -               32',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq(
 | |
|         { { type = 4, timestamp = 0, data = {
 | |
|           0,
 | |
|           '',
 | |
|           32,
 | |
|         } } },
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  CMD',
 | |
|           '  - contents      ""',
 | |
|           '  -               32',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq(
 | |
|         { { type = 4, timestamp = 0, data = {
 | |
|           1,
 | |
|           '',
 | |
|           32,
 | |
|         } } },
 | |
|         {
 | |
|           'History entry with timestamp ' .. epoch .. ':',
 | |
|           '  @ Description_  Value',
 | |
|           '  - history type  SEARCH',
 | |
|           '  - contents      ""',
 | |
|           "  - separator     ' '",
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({ { type = 4, timestamp = 0, data = {
 | |
|         1,
 | |
|         '',
 | |
|       } } }, {
 | |
|         'History entry with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description_  Value',
 | |
|         '  - history type  SEARCH',
 | |
|         '  - contents      ""',
 | |
|         '  # Expected more elements in list',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 4, timestamp = 0, data = {
 | |
|         2,
 | |
|         '',
 | |
|       } } }, {
 | |
|         'History entry with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description_  Value',
 | |
|         '  - history type  EXPR',
 | |
|         '  - contents      ""',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 4, timestamp = 0, data = {
 | |
|         3,
 | |
|         '',
 | |
|       } } }, {
 | |
|         'History entry with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description_  Value',
 | |
|         '  - history type  INPUT',
 | |
|         '  - contents      ""',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 4, timestamp = 0, data = {
 | |
|         4,
 | |
|         '',
 | |
|       } } }, {
 | |
|         'History entry with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description_  Value',
 | |
|         '  - history type  DEBUG',
 | |
|         '  - contents      ""',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with register items', function()
 | |
|       strings2sd_eq(
 | |
|         { { type = 5, timestamp = 0, data = {
 | |
|           1,
 | |
|           2,
 | |
|           3,
 | |
|         } } },
 | |
|         {
 | |
|           'Register with timestamp ' .. epoch .. ':',
 | |
|           '  # Unexpected type: array instead of map',
 | |
|           '  = [1, 2, 3]',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({ { type = 5, timestamp = 0, data = { '!map', {} } } }, {
 | |
|         'Register with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Required key missing: n',
 | |
|         '  # Required key missing: rc',
 | |
|         '  + rw   block width  0',
 | |
|         '  + rt   type         CHARACTERWISE',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 5, timestamp = 0, data = {
 | |
|         n = (' '):byte(),
 | |
|       } } }, {
 | |
|         'Register with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         "  + n    name         ' '",
 | |
|         '  # Required key missing: rc',
 | |
|         '  + rw   block width  0',
 | |
|         '  + rt   type         CHARACTERWISE',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 5,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             n = (' '):byte(),
 | |
|             rc = { 'abc', 'def' },
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Register with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         "  + n    name         ' '",
 | |
|         '  + rc   contents     ["abc", "def"]',
 | |
|         '  + rw   block width  0',
 | |
|         '  + rt   type         CHARACTERWISE',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 5,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             n = (' '):byte(),
 | |
|             rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Register with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         "  + n    name         ' '",
 | |
|         '  + rc   contents     @',
 | |
|         '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|         '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|         '  + rw   block width  0',
 | |
|         '  + rt   type         CHARACTERWISE',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 5,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             n = (' '):byte(),
 | |
|             rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
 | |
|             rw = 5,
 | |
|             rt = 1,
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Register with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         "  + n    name         ' '",
 | |
|         '  + rc   contents     @',
 | |
|         '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|         '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|         '  + rw   block width  5',
 | |
|         '  + rt   type         LINEWISE',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 5,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             n = (' '):byte(),
 | |
|             rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
 | |
|             rw = 5,
 | |
|             rt = 2,
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Register with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         "  + n    name         ' '",
 | |
|         '  + rc   contents     @',
 | |
|         '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|         '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|         '  + rw   block width  5',
 | |
|         '  + rt   type         BLOCKWISE',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 5,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             n = (' '):byte(),
 | |
|             rc = 0,
 | |
|             rw = -1,
 | |
|             rt = 10,
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Register with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         "  + n    name         ' '",
 | |
|         '  # Expected array value',
 | |
|         '  + rc   contents     0',
 | |
|         '  # Value is negative',
 | |
|         '  + rw   block width  -1',
 | |
|         '  # Unexpected enum value: expected one of 0 (CHARACTERWISE), '
 | |
|           .. '1 (LINEWISE), 2 (BLOCKWISE)',
 | |
|         '  + rt   type         10',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with variable items', function()
 | |
|       strings2sd_eq({ { type = 6, timestamp = 0, data = {
 | |
|         a = { 10 },
 | |
|       } } }, {
 | |
|         'Variable with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: map instead of array',
 | |
|         '  = {"a": [10]}',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 6, timestamp = 0, data = {} } }, {
 | |
|         'Variable with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description  Value',
 | |
|         '  # Expected more elements in list',
 | |
|       })
 | |
|       strings2sd_eq({ { type = 6, timestamp = 0, data = {
 | |
|         'foo',
 | |
|       } } }, {
 | |
|         'Variable with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description  Value',
 | |
|         '  - name         "foo"',
 | |
|         '  # Expected more elements in list',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 6,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             'foo',
 | |
|             { '!nil', 0 },
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Variable with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description  Value',
 | |
|         '  - name         "foo"',
 | |
|         '  - value        NIL',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 6,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             'foo',
 | |
|             { '!nil', 0 },
 | |
|             { '!nil', 0 },
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Variable with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description  Value',
 | |
|         '  - name         "foo"',
 | |
|         '  - value        NIL',
 | |
|         '  -              NIL',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with global mark items', function()
 | |
|       strings2sd_eq(
 | |
|         { { type = 7, timestamp = 0, data = {
 | |
|           1,
 | |
|           2,
 | |
|           3,
 | |
|         } } },
 | |
|         {
 | |
|           'Global mark with timestamp ' .. epoch .. ':',
 | |
|           '  # Unexpected type: array instead of map',
 | |
|           '  = [1, 2, 3]',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 7,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             n = ('A'):byte(),
 | |
|             f = 'foo',
 | |
|             l = 2,
 | |
|             c = 200,
 | |
|             mX = 10,
 | |
|             mYYYYYYYYYY = 10,
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Global mark with timestamp ' .. epoch .. ':',
 | |
|         '  % Key________  Description  Value',
 | |
|         "  + n            name         'A'",
 | |
|         '  + f            file name    "foo"',
 | |
|         '  + l            line number  2',
 | |
|         '  + c            column       200',
 | |
|         '  + mX                        10',
 | |
|         '  + mYYYYYYYYYY               10',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with jump items', function()
 | |
|       strings2sd_eq(
 | |
|         { { type = 8, timestamp = 0, data = {
 | |
|           1,
 | |
|           2,
 | |
|           3,
 | |
|         } } },
 | |
|         {
 | |
|           'Jump with timestamp ' .. epoch .. ':',
 | |
|           '  # Unexpected type: array instead of map',
 | |
|           '  = [1, 2, 3]',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 8,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             n = ('A'):byte(),
 | |
|             f = 'foo',
 | |
|             l = 2,
 | |
|             c = 200,
 | |
|             mX = 10,
 | |
|             mYYYYYYYYYY = 10,
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Jump with timestamp ' .. epoch .. ':',
 | |
|         '  % Key________  Description  Value',
 | |
|         "  + n            name         'A'",
 | |
|         '  + f            file name    "foo"',
 | |
|         '  + l            line number  2',
 | |
|         '  + c            column       200',
 | |
|         '  + mX                        10',
 | |
|         '  + mYYYYYYYYYY               10',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with buffer list items', function()
 | |
|       strings2sd_eq({ { type = 9, timestamp = 0, data = {
 | |
|         a = { 10 },
 | |
|       } } }, {
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  # Unexpected type: map instead of array',
 | |
|         '  = {"a": [10]}',
 | |
|       })
 | |
|       strings2sd_eq(
 | |
|         { { type = 9, timestamp = 0, data = {
 | |
|           { a = 10 },
 | |
|           {},
 | |
|         } } },
 | |
|         {
 | |
|           'Buffer list with timestamp ' .. epoch .. ':',
 | |
|           '  # Expected array of maps',
 | |
|           '  = [{"a": 10}, []]',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({ { type = 9, timestamp = 0, data = {
 | |
|         { a = 10 },
 | |
|       } } }, {
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Required key missing: f',
 | |
|         '  + l    line number  1',
 | |
|         '  + c    column       0',
 | |
|         '  + a                 10',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 9,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             { l = '10', c = '10', a = 10 },
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Required key missing: f',
 | |
|         '  # Expected integer',
 | |
|         '  + l    line number  "10"',
 | |
|         '  # Expected integer',
 | |
|         '  + c    column       "10"',
 | |
|         '  + a                 10',
 | |
|       })
 | |
|       strings2sd_eq(
 | |
|         { { type = 9, timestamp = 0, data = {
 | |
|           { l = 10, c = 10, a = 10 },
 | |
|         } } },
 | |
|         {
 | |
|           'Buffer list with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: f',
 | |
|           '  + l    line number  10',
 | |
|           '  + c    column       10',
 | |
|           '  + a                 10',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq(
 | |
|         { { type = 9, timestamp = 0, data = {
 | |
|           { l = -10, c = -10 },
 | |
|         } } },
 | |
|         {
 | |
|           'Buffer list with timestamp ' .. epoch .. ':',
 | |
|           '  % Key  Description  Value',
 | |
|           '  # Required key missing: f',
 | |
|           '  # Value is negative',
 | |
|           '  + l    line number  -10',
 | |
|           '  # Value is negative',
 | |
|           '  + c    column       -10',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({ { type = 9, timestamp = 0, data = {
 | |
|         { f = 'abc' },
 | |
|       } } }, {
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  + f    file name    "abc"',
 | |
|         '  + l    line number  1',
 | |
|         '  + c    column       0',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 9,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             { f = 10 },
 | |
|             { f = 20 },
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Expected binary string',
 | |
|         "  + f    file name    '\\10'",
 | |
|         '  + l    line number  1',
 | |
|         '  + c    column       0',
 | |
|         '',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Expected binary string',
 | |
|         "  + f    file name    '\\20'",
 | |
|         '  + l    line number  1',
 | |
|         '  + c    column       0',
 | |
|       })
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 9,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             { f = 10 },
 | |
|             { f = { '!string', { '\n' } } },
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Buffer list with timestamp ' .. epoch .. ':',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Expected binary string',
 | |
|         "  + f    file name    '\\10'",
 | |
|         '  + l    line number  1',
 | |
|         '  + c    column       0',
 | |
|         '',
 | |
|         '  % Key  Description  Value',
 | |
|         '  # Expected no NUL bytes',
 | |
|         '  + f    file name    "\\0"',
 | |
|         '  + l    line number  1',
 | |
|         '  + c    column       0',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with local mark items', function()
 | |
|       strings2sd_eq(
 | |
|         { { type = 10, timestamp = 0, data = {
 | |
|           1,
 | |
|           2,
 | |
|           3,
 | |
|         } } },
 | |
|         {
 | |
|           'Local mark with timestamp ' .. epoch .. ':',
 | |
|           '  # Unexpected type: array instead of map',
 | |
|           '  = [1, 2, 3]',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 10,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             n = ('A'):byte(),
 | |
|             f = 'foo',
 | |
|             l = 2,
 | |
|             c = 200,
 | |
|             mX = 10,
 | |
|             mYYYYYYYYYY = 10,
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Local mark with timestamp ' .. epoch .. ':',
 | |
|         '  % Key________  Description  Value',
 | |
|         "  + n            name         'A'",
 | |
|         '  + f            file name    "foo"',
 | |
|         '  + l            line number  2',
 | |
|         '  + c            column       200',
 | |
|         '  + mX                        10',
 | |
|         '  + mYYYYYYYYYY               10',
 | |
|       })
 | |
|     end)
 | |
| 
 | |
|     it('works with change items', function()
 | |
|       strings2sd_eq(
 | |
|         { { type = 11, timestamp = 0, data = {
 | |
|           1,
 | |
|           2,
 | |
|           3,
 | |
|         } } },
 | |
|         {
 | |
|           'Change with timestamp ' .. epoch .. ':',
 | |
|           '  # Unexpected type: array instead of map',
 | |
|           '  = [1, 2, 3]',
 | |
|         }
 | |
|       )
 | |
|       strings2sd_eq({
 | |
|         {
 | |
|           type = 11,
 | |
|           timestamp = 0,
 | |
|           data = {
 | |
|             n = ('A'):byte(),
 | |
|             f = 'foo',
 | |
|             l = 2,
 | |
|             c = 200,
 | |
|             mX = 10,
 | |
|             mYYYYYYYYYY = 10,
 | |
|           },
 | |
|         },
 | |
|       }, {
 | |
|         'Change with timestamp ' .. epoch .. ':',
 | |
|         '  % Key________  Description  Value',
 | |
|         "  + n            name         'A'",
 | |
|         '  + f            file name    "foo"',
 | |
|         '  + l            line number  2',
 | |
|         '  + c            column       200',
 | |
|         '  + mX                        10',
 | |
|         '  + mYYYYYYYYYY               10',
 | |
|       })
 | |
|     end)
 | |
|   end)
 | |
| 
 | |
|   describe('function shada#get_binstrings', function()
 | |
|     local getbstrings_eq = function(expected, input)
 | |
|       local result = fn['shada#get_binstrings'](input)
 | |
|       for i, s in ipairs(result) do
 | |
|         result[i] = s:gsub('\n', '\0')
 | |
|       end
 | |
|       local mpack_result = table.concat(result, '\n')
 | |
|       return mpack_eq(expected, mpack_result)
 | |
|     end
 | |
| 
 | |
|     it('works', function()
 | |
|       local version = api.nvim_get_vvar('version')
 | |
|       getbstrings_eq({
 | |
|         {
 | |
|           timestamp = 'current',
 | |
|           type = 1,
 | |
|           value = {
 | |
|             generator = 'shada.vim',
 | |
|             version = version,
 | |
|           },
 | |
|         },
 | |
|       }, {})
 | |
|       getbstrings_eq({
 | |
|         {
 | |
|           timestamp = 'current',
 | |
|           type = 1,
 | |
|           value = {
 | |
|             generator = 'shada.vim',
 | |
|             version = version,
 | |
|           },
 | |
|         },
 | |
|         { timestamp = 0, type = 1, value = { generator = 'test' } },
 | |
|       }, {
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key______  Value',
 | |
|         '  + generator  "test"',
 | |
|       })
 | |
|       api.nvim_set_var('shada#add_own_header', 1)
 | |
|       getbstrings_eq({
 | |
|         {
 | |
|           timestamp = 'current',
 | |
|           type = 1,
 | |
|           value = {
 | |
|             generator = 'shada.vim',
 | |
|             version = version,
 | |
|           },
 | |
|         },
 | |
|       }, {})
 | |
|       getbstrings_eq({
 | |
|         {
 | |
|           timestamp = 'current',
 | |
|           type = 1,
 | |
|           value = {
 | |
|             generator = 'shada.vim',
 | |
|             version = version,
 | |
|           },
 | |
|         },
 | |
|         { timestamp = 0, type = 1, value = { generator = 'test' } },
 | |
|       }, {
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key______  Value',
 | |
|         '  + generator  "test"',
 | |
|       })
 | |
|       api.nvim_set_var('shada#add_own_header', 0)
 | |
|       getbstrings_eq({}, {})
 | |
|       getbstrings_eq({ { timestamp = 0, type = 1, value = { generator = 'test' } } }, {
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key______  Value',
 | |
|         '  + generator  "test"',
 | |
|       })
 | |
|       api.nvim_set_var('shada#keep_old_header', 0)
 | |
|       getbstrings_eq({}, {
 | |
|         'Header with timestamp ' .. epoch .. ':',
 | |
|         '  % Key______  Value',
 | |
|         '  + generator  "test"',
 | |
|       })
 | |
|       getbstrings_eq({
 | |
|         { type = 3, timestamp = 0, value = { 'abc\ndef' } },
 | |
|         { type = 3, timestamp = 0, value = { 'abc\ndef' } },
 | |
|         { type = 3, timestamp = 0, value = { 'abc\ndef' } },
 | |
|       }, {
 | |
|         'Replacement string with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description__________  Value',
 | |
|         '  - :s replacement string  "abc\\ndef"',
 | |
|         'Replacement string with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description__________  Value',
 | |
|         '  - :s replacement string  "abc\\ndef"',
 | |
|         'Replacement string with timestamp ' .. epoch .. ':',
 | |
|         '  @ Description__________  Value',
 | |
|         '  - :s replacement string  "abc\\ndef"',
 | |
|       })
 | |
|     end)
 | |
|   end)
 | |
| end)
 | |
| 
 | |
| describe('plugin/shada.vim', function()
 | |
|   local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
 | |
|   local eol = t.is_os('win') and '\r\n' or '\n'
 | |
|   before_each(function()
 | |
|     -- Note: reset() is called explicitly in each test.
 | |
|     os.remove(fname)
 | |
|     os.remove(fname .. '.tst')
 | |
|     os.remove(fname_tmp)
 | |
|   end)
 | |
| 
 | |
|   teardown(function()
 | |
|     os.remove(fname)
 | |
|     os.remove(fname .. '.tst')
 | |
|     os.remove(fname_tmp)
 | |
|   end)
 | |
| 
 | |
|   local shada_eq = function(expected, fname_)
 | |
|     local mpack_result = read_file(fname_)
 | |
|     mpack_eq(expected, mpack_result)
 | |
|   end
 | |
| 
 | |
|   it('event BufReadCmd', function()
 | |
|     reset()
 | |
|     wshada('\004\000\009\147\000\196\002ab\196\001a')
 | |
|     wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
 | |
| 
 | |
|     local bufread_commands = api.nvim_get_autocmds({ group = 'nvim.shada', event = 'BufReadCmd' })
 | |
|     eq(2, #bufread_commands--[[, vim.inspect(bufread_commands) ]])
 | |
| 
 | |
|     -- Need to set nohidden so that the buffer containing 'fname' is not unloaded
 | |
|     -- after loading 'fname_tmp', otherwise the '++opt not supported' test below
 | |
|     -- won't work since the BufReadCmd autocmd won't be triggered.
 | |
|     nvim_command('set nohidden')
 | |
| 
 | |
|     nvim_command('edit ' .. fname)
 | |
|     eq({
 | |
|       'History entry with timestamp ' .. epoch .. ':',
 | |
|       '  @ Description_  Value',
 | |
|       '  - history type  CMD',
 | |
|       '  - contents      "ab"',
 | |
|       '  -               "a"',
 | |
|     }, nvim_eval('getline(1, "$")'))
 | |
|     eq(false, api.nvim_get_option_value('modified', {}))
 | |
|     eq('shada', api.nvim_get_option_value('filetype', {}))
 | |
|     nvim_command('edit ' .. fname_tmp)
 | |
|     eq({
 | |
|       'History entry with timestamp ' .. epoch .. ':',
 | |
|       '  @ Description_  Value',
 | |
|       '  - history type  CMD',
 | |
|       '  - contents      "ab"',
 | |
|       '  -               "b"',
 | |
|     }, nvim_eval('getline(1, "$")'))
 | |
|     eq(false, api.nvim_get_option_value('modified', {}))
 | |
|     eq('shada', api.nvim_get_option_value('filetype', {}))
 | |
|     t.matches(
 | |
|       '++opt not supported',
 | |
|       t.pcall_err(function()
 | |
|         nvim_command('edit ++enc=latin1 ' .. fname)
 | |
|       end)
 | |
|     )
 | |
|     neq({
 | |
|       'History entry with timestamp ' .. epoch .. ':',
 | |
|       '  @ Description_  Value',
 | |
|       '  - history type  CMD',
 | |
|       '  - contents      "ab"',
 | |
|       '  -               "a"',
 | |
|     }, nvim_eval('getline(1, "$")'))
 | |
|     neq(true, api.nvim_get_option_value('modified', {}))
 | |
|   end)
 | |
| 
 | |
|   it('event FileReadCmd', function()
 | |
|     reset()
 | |
|     wshada('\004\000\009\147\000\196\002ab\196\001a')
 | |
|     wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
 | |
|     nvim_command('$read ' .. fname)
 | |
|     eq({
 | |
|       '',
 | |
|       'History entry with timestamp ' .. epoch .. ':',
 | |
|       '  @ Description_  Value',
 | |
|       '  - history type  CMD',
 | |
|       '  - contents      "ab"',
 | |
|       '  -               "a"',
 | |
|     }, nvim_eval('getline(1, "$")'))
 | |
|     eq(true, api.nvim_get_option_value('modified', {}))
 | |
|     neq('shada', api.nvim_get_option_value('filetype', {}))
 | |
|     nvim_command('1,$read ' .. fname_tmp)
 | |
|     eq({
 | |
|       '',
 | |
|       'History entry with timestamp ' .. epoch .. ':',
 | |
|       '  @ Description_  Value',
 | |
|       '  - history type  CMD',
 | |
|       '  - contents      "ab"',
 | |
|       '  -               "a"',
 | |
|       'History entry with timestamp ' .. epoch .. ':',
 | |
|       '  @ Description_  Value',
 | |
|       '  - history type  CMD',
 | |
|       '  - contents      "ab"',
 | |
|       '  -               "b"',
 | |
|     }, nvim_eval('getline(1, "$")'))
 | |
|     eq(true, api.nvim_get_option_value('modified', {}))
 | |
|     neq('shada', api.nvim_get_option_value('filetype', {}))
 | |
|     api.nvim_set_option_value('modified', false, {})
 | |
|     t.matches(
 | |
|       '++opt not supported',
 | |
|       t.pcall_err(function()
 | |
|         nvim_command('$read ++enc=latin1 ' .. fname)
 | |
|       end)
 | |
|     )
 | |
|     eq({
 | |
|       '',
 | |
|       'History entry with timestamp ' .. epoch .. ':',
 | |
|       '  @ Description_  Value',
 | |
|       '  - history type  CMD',
 | |
|       '  - contents      "ab"',
 | |
|       '  -               "a"',
 | |
|       'History entry with timestamp ' .. epoch .. ':',
 | |
|       '  @ Description_  Value',
 | |
|       '  - history type  CMD',
 | |
|       '  - contents      "ab"',
 | |
|       '  -               "b"',
 | |
|     }, nvim_eval('getline(1, "$")'))
 | |
|     neq(true, api.nvim_get_option_value('modified', {}))
 | |
|   end)
 | |
| 
 | |
|   it('event BufWriteCmd', function()
 | |
|     reset()
 | |
|     api.nvim_set_var('shada#add_own_header', 0)
 | |
|     api.nvim_buf_set_lines(0, 0, 1, true, {
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|     })
 | |
|     nvim_command('w ' .. fname .. '.tst')
 | |
|     nvim_command('w ' .. fname)
 | |
|     nvim_command('w ' .. fname_tmp)
 | |
|     t.matches(
 | |
|       '++opt not supported',
 | |
|       t.pcall_err(function()
 | |
|         nvim_command('w! ++enc=latin1 ' .. fname)
 | |
|       end)
 | |
|     )
 | |
|     eq(table.concat({
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|     }, eol) .. eol, read_file(fname .. '.tst'))
 | |
|     shada_eq({
 | |
|       {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
 | |
|       },
 | |
|       {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
 | |
|       },
 | |
|     }, fname)
 | |
|     shada_eq({
 | |
|       {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
 | |
|       },
 | |
|       {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
 | |
|       },
 | |
|     }, fname_tmp)
 | |
|   end)
 | |
| 
 | |
|   it('event FileWriteCmd', function()
 | |
|     reset()
 | |
|     api.nvim_set_var('shada#add_own_header', 0)
 | |
|     api.nvim_buf_set_lines(0, 0, 1, true, {
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|     })
 | |
|     nvim_command('1,3w ' .. fname .. '.tst')
 | |
|     nvim_command('1,3w ' .. fname)
 | |
|     nvim_command('1,3w ' .. fname_tmp)
 | |
|     t.matches(
 | |
|       '++opt not supported',
 | |
|       t.pcall_err(function()
 | |
|         nvim_command('1,3w! ++enc=latin1 ' .. fname)
 | |
|       end)
 | |
|     )
 | |
|     eq(table.concat({
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|     }, eol) .. eol, read_file(fname .. '.tst'))
 | |
|     shada_eq(
 | |
|       { {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { n = ('A'):byte() },
 | |
|       } },
 | |
|       fname
 | |
|     )
 | |
|     shada_eq(
 | |
|       { {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { n = ('A'):byte() },
 | |
|       } },
 | |
|       fname_tmp
 | |
|     )
 | |
|   end)
 | |
| 
 | |
|   it('event FileAppendCmd', function()
 | |
|     reset()
 | |
|     api.nvim_set_var('shada#add_own_header', 0)
 | |
|     api.nvim_buf_set_lines(0, 0, 1, true, {
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|     })
 | |
|     fn.writefile({ '' }, fname .. '.tst', 'b')
 | |
|     fn.writefile({ '' }, fname, 'b')
 | |
|     fn.writefile({ '' }, fname_tmp, 'b')
 | |
|     nvim_command('1,3w >> ' .. fname .. '.tst')
 | |
|     nvim_command('1,3w >> ' .. fname)
 | |
|     nvim_command('1,3w >> ' .. fname_tmp)
 | |
|     nvim_command('w >> ' .. fname .. '.tst')
 | |
|     nvim_command('w >> ' .. fname)
 | |
|     nvim_command('w >> ' .. fname_tmp)
 | |
|     t.matches(
 | |
|       '++opt not supported',
 | |
|       t.pcall_err(function()
 | |
|         nvim_command('1,3w! ++enc=latin1 >> ' .. fname)
 | |
|       end)
 | |
|     )
 | |
|     eq(table.concat({
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|     }, eol) .. eol, read_file(fname .. '.tst'))
 | |
|     shada_eq({
 | |
|       {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { n = ('A'):byte() },
 | |
|       },
 | |
|       {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
 | |
|       },
 | |
|       {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
 | |
|       },
 | |
|     }, fname)
 | |
|     shada_eq({
 | |
|       {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { n = ('A'):byte() },
 | |
|       },
 | |
|       {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
 | |
|       },
 | |
|       {
 | |
|         timestamp = 0,
 | |
|         type = 8,
 | |
|         value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
 | |
|       },
 | |
|     }, fname_tmp)
 | |
|   end)
 | |
| 
 | |
|   it('event SourceCmd', function()
 | |
|     reset(fname)
 | |
|     finally(function()
 | |
|       nvim_command('set shadafile=NONE') -- Avoid writing shada file on exit
 | |
|     end)
 | |
|     wshada('\004\000\006\146\000\196\002ab')
 | |
|     wshada_tmp('\004\001\006\146\000\196\002bc')
 | |
|     eq(0, exc_exec('source ' .. fname))
 | |
|     eq(0, exc_exec('source ' .. fname_tmp))
 | |
|     eq('bc', fn.histget(':', -1))
 | |
|     eq('ab', fn.histget(':', -2))
 | |
|   end)
 | |
| end)
 | |
| 
 | |
| describe('ftplugin/shada.vim', function()
 | |
|   local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
 | |
|   before_each(reset)
 | |
| 
 | |
|   it('sets indentexpr correctly', function()
 | |
|     nvim_command('filetype plugin indent on')
 | |
|     nvim_command('setlocal filetype=shada')
 | |
|     fn.setline(1, {
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '% Key________  Description  Value',
 | |
|       "+ n            name         'A'",
 | |
|       '+ f            file name    "foo"',
 | |
|       '+ l            line number  2',
 | |
|       '+ c            column       200',
 | |
|       '+ mX                        10',
 | |
|       '+ mYYYYYYYYYY               10',
 | |
|       'Register with timestamp ' .. epoch .. ':',
 | |
|       '% Key  Description  Value',
 | |
|       "+ n    name         ' '",
 | |
|       '+ rc   contents     @',
 | |
|       '| - "abcdefghijklmnopqrstuvwxyz"',
 | |
|       '| - "abcdefghijklmnopqrstuvwxyz"',
 | |
|       '+ rw   block width  0',
 | |
|       '+ rt   type         CHARACTERWISE',
 | |
|       'Replacement string with timestamp ' .. epoch .. ':',
 | |
|       '    @ Description__________  Value',
 | |
|       '    - :s replacement string  "abc\\ndef"',
 | |
|       '   Buffer list with timestamp ' .. epoch .. ':',
 | |
|       '    # Expected array of maps',
 | |
|       '= [{"a": 10}, []]',
 | |
|       '    Buffer list with timestamp ' .. epoch .. ':',
 | |
|       '   % Key  Description  Value',
 | |
|       '  # Expected binary string',
 | |
|       '+ f    file name    10',
 | |
|       ' + l    line number  1',
 | |
|       '   + c    column       0',
 | |
|       '',
 | |
|       ' % Key  Description  Value',
 | |
|       '    # Expected binary string',
 | |
|       ' + f    file name    20',
 | |
|       '+ l    line number  1',
 | |
|       '    + c    column       0',
 | |
|     })
 | |
|     nvim_command('normal! gg=G')
 | |
|     eq({
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    "foo"',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       200',
 | |
|       '  + mX                        10',
 | |
|       '  + mYYYYYYYYYY               10',
 | |
|       'Register with timestamp ' .. epoch .. ':',
 | |
|       '  % Key  Description  Value',
 | |
|       "  + n    name         ' '",
 | |
|       '  + rc   contents     @',
 | |
|       '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|       '  | - "abcdefghijklmnopqrstuvwxyz"',
 | |
|       '  + rw   block width  0',
 | |
|       '  + rt   type         CHARACTERWISE',
 | |
|       'Replacement string with timestamp ' .. epoch .. ':',
 | |
|       '  @ Description__________  Value',
 | |
|       '  - :s replacement string  "abc\\ndef"',
 | |
|       'Buffer list with timestamp ' .. epoch .. ':',
 | |
|       '  # Expected array of maps',
 | |
|       '  = [{"a": 10}, []]',
 | |
|       'Buffer list with timestamp ' .. epoch .. ':',
 | |
|       '  % Key  Description  Value',
 | |
|       '  # Expected binary string',
 | |
|       '  + f    file name    10',
 | |
|       '  + l    line number  1',
 | |
|       '  + c    column       0',
 | |
|       '',
 | |
|       '  % Key  Description  Value',
 | |
|       '  # Expected binary string',
 | |
|       '  + f    file name    20',
 | |
|       '  + l    line number  1',
 | |
|       '  + c    column       0',
 | |
|     }, fn.getline(1, fn.line('$')))
 | |
|   end)
 | |
| 
 | |
|   it('sets options correctly', function()
 | |
|     nvim_command('filetype plugin indent on')
 | |
|     nvim_command('setlocal filetype=shada')
 | |
|     eq(true, api.nvim_get_option_value('expandtab', {}))
 | |
|     eq(2, api.nvim_get_option_value('tabstop', {}))
 | |
|     eq(2, api.nvim_get_option_value('softtabstop', {}))
 | |
|     eq(2, api.nvim_get_option_value('shiftwidth', {}))
 | |
|   end)
 | |
| 
 | |
|   it('sets indentkeys correctly', function()
 | |
|     nvim_command('filetype plugin indent on')
 | |
|     nvim_command('setlocal filetype=shada')
 | |
|     fn.setline(1, '  Replacement with timestamp ' .. epoch)
 | |
|     nvim_feed('ggA:\027')
 | |
|     eq('Replacement with timestamp ' .. epoch .. ':', api.nvim_buf_get_lines(0, 0, 1, true)[1])
 | |
|     nvim_feed('o-\027')
 | |
|     eq({ '  -' }, api.nvim_buf_get_lines(0, 1, 2, true))
 | |
|     nvim_feed('ggO+\027')
 | |
|     eq({ '+' }, api.nvim_buf_get_lines(0, 0, 1, true))
 | |
|     nvim_feed('GO*\027')
 | |
|     eq({ '  *' }, api.nvim_buf_get_lines(0, 2, 3, true))
 | |
|     nvim_feed('ggO  /\027')
 | |
|     eq({ '  /' }, api.nvim_buf_get_lines(0, 0, 1, true))
 | |
|     nvim_feed('ggOx\027')
 | |
|     eq({ 'x' }, api.nvim_buf_get_lines(0, 0, 1, true))
 | |
|   end)
 | |
| end)
 | |
| 
 | |
| describe('syntax/shada.vim', function()
 | |
|   local epoch = os.date('!%Y-%m-%dT%H:%M:%S', 0)
 | |
|   before_each(reset)
 | |
| 
 | |
|   it('works', function()
 | |
|     nvim_command('syntax on')
 | |
|     nvim_command('setlocal syntax=shada')
 | |
|     nvim_command('set laststatus&')
 | |
|     local screen = Screen.new(60, 37)
 | |
|     screen:set_default_attr_ids {
 | |
|       [1] = { bold = true, foreground = Screen.colors.Brown },
 | |
|       [2] = { foreground = tonumber('0x6a0dad') },
 | |
|       [3] = { foreground = Screen.colors.Fuchsia },
 | |
|       [4] = { foreground = Screen.colors.Blue1 },
 | |
|       [5] = { bold = true, foreground = Screen.colors.SeaGreen4 },
 | |
|       [6] = { foreground = Screen.colors.SlateBlue },
 | |
|       [7] = { bold = true, reverse = true },
 | |
|       [8] = { bold = true, foreground = Screen.colors.Blue },
 | |
|     }
 | |
| 
 | |
|     api.nvim_buf_set_lines(0, 0, 1, true, {
 | |
|       'Header with timestamp ' .. epoch .. ':',
 | |
|       '  % Key  Value',
 | |
|       '  + t    "test"',
 | |
|       'Jump with timestamp ' .. epoch .. ':',
 | |
|       '  % Key________  Description  Value',
 | |
|       "  + n            name         'A'",
 | |
|       '  + f            file name    ["foo"]',
 | |
|       '  + l            line number  2',
 | |
|       '  + c            column       -200',
 | |
|       'Register with timestamp ' .. epoch .. ':',
 | |
|       '  % Key  Description  Value',
 | |
|       '  + rc   contents     @',
 | |
|       '  | - {"abcdefghijklmnopqrstuvwxyz": 1.0}',
 | |
|       '  + rt   type         CHARACTERWISE',
 | |
|       '  + rt   type         LINEWISE',
 | |
|       '  + rt   type         BLOCKWISE',
 | |
|       'Replacement string with timestamp ' .. epoch .. ':',
 | |
|       '  @ Description__________  Value',
 | |
|       '  - :s replacement string  CMD',
 | |
|       '  - :s replacement string  SEARCH',
 | |
|       '  - :s replacement string  EXPR',
 | |
|       '  - :s replacement string  INPUT',
 | |
|       '  - :s replacement string  DEBUG',
 | |
|       'Buffer list with timestamp ' .. epoch .. ':',
 | |
|       '  # Expected array of maps',
 | |
|       '  = [{"a": +(10)"ac\\0df\\ngi\\"tt\\.", TRUE: FALSE}, [NIL, +(-10)""]]',
 | |
|       'Buffer list with timestamp ' .. epoch .. ':',
 | |
|       '  % Key  Description  Value',
 | |
|       '',
 | |
|       '  % Key  Description  Value',
 | |
|       'Header with timestamp ' .. epoch .. ':',
 | |
|       '  % Key  Description________  Value',
 | |
|       '  + se   place cursor at end  TRUE',
 | |
|     })
 | |
|     screen:expect {
 | |
|       grid = [=[
 | |
|       {1:^Header} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00:                  |
 | |
|       {2:  % Key  Value}                                              |
 | |
|        {1: +} {3:t  }  {1:"}{3:test}{1:"}                                             |
 | |
|       {1:Jump} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00:                    |
 | |
|       {2:  % Key________  Description  Value}                         |
 | |
|        {1: +} {3:n          }  {4:name       }  {3:'A'}                           |
 | |
|        {1: +} {3:f          }  {4:file name  }  {1:["}{3:foo}{1:"]}                       |
 | |
|        {1: +} {3:l          }  {4:line number}  {3:2}                             |
 | |
|        {1: +} {3:c          }  {4:column     }  {3:-200}                          |
 | |
|       {1:Register} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00:                |
 | |
|       {2:  % Key  Description  Value}                                 |
 | |
|        {1: +} {3:rc }  {4:contents   }  {1:@}                                     |
 | |
|        {1: | -} {1:{"}{3:abcdefghijklmnopqrstuvwxyz}{1:":} {3:1.0}{1:}}                   |
 | |
|        {1: +} {3:rt }  {4:type       }  {1:CHARACTERWISE}                         |
 | |
|        {1: +} {3:rt }  {4:type       }  {1:LINEWISE}                              |
 | |
|        {1: +} {3:rt }  {4:type       }  {1:BLOCKWISE}                             |
 | |
|       {1:Replacement string} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00:      |
 | |
|       {2:  @ Description__________  Value}                            |
 | |
|        {1: -} {4::s replacement string}  {1:CMD}                              |
 | |
|        {1: -} {4::s replacement string}  {1:SEARCH}                           |
 | |
|        {1: -} {4::s replacement string}  {1:EXPR}                             |
 | |
|        {1: -} {4::s replacement string}  {1:INPUT}                            |
 | |
|        {1: -} {4::s replacement string}  {1:DEBUG}                            |
 | |
|       {1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00:             |
 | |
|       {4:  # Expected array of maps}                                  |
 | |
|         = {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}|
 | |
|       {5:0}{1:)""]]}                                                      |
 | |
|       {1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00:             |
 | |
|       {2:  % Key  Description  Value}                                 |
 | |
|                                                                   |
 | |
|       {2:  % Key  Description  Value}                                 |
 | |
|       {1:Header} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00:                  |
 | |
|       {2:  % Key  Description________  Value}                         |
 | |
|        {1: +} {3:se }  {4:place cursor at end}  {1:TRUE}                          |
 | |
|       {8:~                                                           }|
 | |
|       {7:[No Name] [+]                                               }|
 | |
|                                                                   |
 | |
|     ]=],
 | |
|     }
 | |
| 
 | |
|     nvim_command([[
 | |
|       function GetSyntax()
 | |
|         let lines = []
 | |
|         for l in range(1, line('$'))
 | |
|           let columns = []
 | |
|           let line = getline(l)
 | |
|           for c in range(1, col([l, '$']) - 1)
 | |
|             let synstack = map(synstack(l, c), 'synIDattr(v:val, "name")')
 | |
|             if !empty(columns) && columns[-1][0] ==# synstack
 | |
|               let columns[-1][1] .= line[c - 1]
 | |
|             else
 | |
|               call add(columns, [ synstack, line[c - 1] ])
 | |
|             endif
 | |
|           endfor
 | |
|           call add(lines, columns)
 | |
|         endfor
 | |
|         return lines
 | |
|       endfunction
 | |
|     ]])
 | |
|     local hname = function(s)
 | |
|       return { { 'ShaDaEntryHeader', 'ShaDaEntryName' }, s }
 | |
|     end
 | |
|     local h = function(s)
 | |
|       return { { 'ShaDaEntryHeader' }, s }
 | |
|     end
 | |
|     local htsnum = function(s)
 | |
|       return {
 | |
|         { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp', 'ShaDaEntryTimestampNumber' },
 | |
|         s,
 | |
|       }
 | |
|     end
 | |
|     local synhtssep = function(s)
 | |
|       return { { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp' }, s }
 | |
|     end
 | |
|     local synepoch = {
 | |
|       year = htsnum(os.date('!%Y', 0)),
 | |
|       month = htsnum(os.date('!%m', 0)),
 | |
|       day = htsnum(os.date('!%d', 0)),
 | |
|       hour = htsnum(os.date('!%H', 0)),
 | |
|       minute = htsnum(os.date('!%M', 0)),
 | |
|       second = htsnum(os.date('!%S', 0)),
 | |
|     }
 | |
|     local msh = function(s)
 | |
|       return {
 | |
|         { 'ShaDaEntryMapShort', 'ShaDaEntryMapHeader' },
 | |
|         s,
 | |
|       }
 | |
|     end
 | |
|     local mlh = function(s)
 | |
|       return { { 'ShaDaEntryMapLong', 'ShaDaEntryMapHeader' }, s }
 | |
|     end
 | |
|     local ah = function(s)
 | |
|       return { { 'ShaDaEntryArray', 'ShaDaEntryArrayHeader' }, s }
 | |
|     end
 | |
|     -- luacheck: ignore
 | |
|     local mses = function(s)
 | |
|       return {
 | |
|         {
 | |
|           'ShaDaEntryMapShort',
 | |
|           'ShaDaEntryMapShortEntryStart',
 | |
|         },
 | |
|         s,
 | |
|       }
 | |
|     end
 | |
|     local mles = function(s)
 | |
|       return {
 | |
|         { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongEntryStart' },
 | |
|         s,
 | |
|       }
 | |
|     end
 | |
|     local act = fn.GetSyntax()
 | |
|     local ms = function(syn)
 | |
|       return {
 | |
|         { 'ShaDaEntryMap' .. syn, 'ShaDaEntryMap' .. syn .. 'EntryStart' },
 | |
|         '  + ',
 | |
|       }
 | |
|     end
 | |
|     local as = function()
 | |
|       return { { 'ShaDaEntryArray', 'ShaDaEntryArrayEntryStart' }, '  - ' }
 | |
|     end
 | |
|     local ad = function(s)
 | |
|       return {
 | |
|         { 'ShaDaEntryArray', 'ShaDaEntryArrayDescription' },
 | |
|         s,
 | |
|       }
 | |
|     end
 | |
|     local mbas = function(syn)
 | |
|       return {
 | |
|         { 'ShaDaEntryMap' .. syn, 'ShaDaEntryMapBinArrayStart' },
 | |
|         '  | - ',
 | |
|       }
 | |
|     end
 | |
|     local msk = function(s)
 | |
|       return {
 | |
|         { 'ShaDaEntryMapShort', 'ShaDaEntryMapShortKey' },
 | |
|         s,
 | |
|       }
 | |
|     end
 | |
|     local mlk = function(s)
 | |
|       return {
 | |
|         { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongKey' },
 | |
|         s,
 | |
|       }
 | |
|     end
 | |
|     local mld = function(s)
 | |
|       return {
 | |
|         { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongDescription' },
 | |
|         s,
 | |
|       }
 | |
|     end
 | |
|     local c = function(s)
 | |
|       return { { 'ShaDaComment' }, s }
 | |
|     end
 | |
|     local exp = {
 | |
|       {
 | |
|         hname('Header'),
 | |
|         h(' with timestamp '),
 | |
|         synepoch.year,
 | |
|         synhtssep('-'),
 | |
|         synepoch.month,
 | |
|         synhtssep('-'),
 | |
|         synepoch.day,
 | |
|         synhtssep('T'),
 | |
|         synepoch.hour,
 | |
|         synhtssep(':'),
 | |
|         synepoch.minute,
 | |
|         synhtssep(':'),
 | |
|         synepoch.second,
 | |
|         h(':'),
 | |
|       },
 | |
|       {
 | |
|         msh('  % Key  Value'),
 | |
|       },
 | |
|       {
 | |
|         ms('Short'),
 | |
|         msk('t    '),
 | |
|         {
 | |
|           { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString', 'ShaDaMsgpackStringQuotes' },
 | |
|           '"',
 | |
|         },
 | |
|         { { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString' }, 'test' },
 | |
|         { { 'ShaDaEntryMapShort', 'ShaDaMsgpackStringQuotes' }, '"' },
 | |
|       },
 | |
|       {
 | |
|         hname('Jump'),
 | |
|         h(' with timestamp '),
 | |
|         synepoch.year,
 | |
|         synhtssep('-'),
 | |
|         synepoch.month,
 | |
|         synhtssep('-'),
 | |
|         synepoch.day,
 | |
|         synhtssep('T'),
 | |
|         synepoch.hour,
 | |
|         synhtssep(':'),
 | |
|         synepoch.minute,
 | |
|         synhtssep(':'),
 | |
|         synepoch.second,
 | |
|         h(':'),
 | |
|       },
 | |
|       {
 | |
|         mlh('  % Key________  Description  Value'),
 | |
|       },
 | |
|       {
 | |
|         ms('Long'),
 | |
|         mlk('n            '),
 | |
|         mld('name         '),
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackCharacter' }, "'A'" },
 | |
|       },
 | |
|       {
 | |
|         ms('Long'),
 | |
|         mlk('f            '),
 | |
|         mld('file name    '),
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
 | |
|         {
 | |
|           {
 | |
|             'ShaDaEntryMapLong',
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackBinaryString',
 | |
|             'ShaDaMsgpackStringQuotes',
 | |
|           },
 | |
|           '"',
 | |
|         },
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString' }, 'foo' },
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' },
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArrayBraces' }, ']' },
 | |
|       },
 | |
|       {
 | |
|         ms('Long'),
 | |
|         mlk('l            '),
 | |
|         mld('line number  '),
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '2' },
 | |
|       },
 | |
|       {
 | |
|         ms('Long'),
 | |
|         mlk('c            '),
 | |
|         mld('column       '),
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '-200' },
 | |
|       },
 | |
|       {
 | |
|         hname('Register'),
 | |
|         h(' with timestamp '),
 | |
|         synepoch.year,
 | |
|         synhtssep('-'),
 | |
|         synepoch.month,
 | |
|         synhtssep('-'),
 | |
|         synepoch.day,
 | |
|         synhtssep('T'),
 | |
|         synepoch.hour,
 | |
|         synhtssep(':'),
 | |
|         synepoch.minute,
 | |
|         synhtssep(':'),
 | |
|         synepoch.second,
 | |
|         h(':'),
 | |
|       },
 | |
|       {
 | |
|         mlh('  % Key  Description  Value'),
 | |
|       },
 | |
|       {
 | |
|         ms('Long'),
 | |
|         mlk('rc   '),
 | |
|         mld('contents     '),
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMultilineArray' }, '@' },
 | |
|       },
 | |
|       {
 | |
|         mbas('Long'),
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' },
 | |
|         {
 | |
|           {
 | |
|             'ShaDaEntryMapLong',
 | |
|             'ShaDaMsgpackMap',
 | |
|             'ShaDaMsgpackBinaryString',
 | |
|             'ShaDaMsgpackStringQuotes',
 | |
|           },
 | |
|           '"',
 | |
|         },
 | |
|         {
 | |
|           { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' },
 | |
|           'abcdefghijklmnopqrstuvwxyz',
 | |
|         },
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap' }, ' ' },
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackFloat' }, '1.0' },
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMapBraces' }, '}' },
 | |
|       },
 | |
|       {
 | |
|         ms('Long'),
 | |
|         mlk('rt   '),
 | |
|         mld('type         '),
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'CHARACTERWISE' },
 | |
|       },
 | |
|       {
 | |
|         ms('Long'),
 | |
|         mlk('rt   '),
 | |
|         mld('type         '),
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'LINEWISE' },
 | |
|       },
 | |
|       {
 | |
|         ms('Long'),
 | |
|         mlk('rt   '),
 | |
|         mld('type         '),
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'BLOCKWISE' },
 | |
|       },
 | |
|       {
 | |
|         hname('Replacement string'),
 | |
|         h(' with timestamp '),
 | |
|         synepoch.year,
 | |
|         synhtssep('-'),
 | |
|         synepoch.month,
 | |
|         synhtssep('-'),
 | |
|         synepoch.day,
 | |
|         synhtssep('T'),
 | |
|         synepoch.hour,
 | |
|         synhtssep(':'),
 | |
|         synepoch.minute,
 | |
|         synhtssep(':'),
 | |
|         synepoch.second,
 | |
|         h(':'),
 | |
|       },
 | |
|       {
 | |
|         ah('  @ Description__________  Value'),
 | |
|       },
 | |
|       {
 | |
|         as(),
 | |
|         ad(':s replacement string  '),
 | |
|         { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'CMD' },
 | |
|       },
 | |
|       {
 | |
|         as(),
 | |
|         ad(':s replacement string  '),
 | |
|         { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'SEARCH' },
 | |
|       },
 | |
|       {
 | |
|         as(),
 | |
|         ad(':s replacement string  '),
 | |
|         { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'EXPR' },
 | |
|       },
 | |
|       {
 | |
|         as(),
 | |
|         ad(':s replacement string  '),
 | |
|         { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'INPUT' },
 | |
|       },
 | |
|       {
 | |
|         as(),
 | |
|         ad(':s replacement string  '),
 | |
|         { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'DEBUG' },
 | |
|       },
 | |
|       {
 | |
|         hname('Buffer list'),
 | |
|         h(' with timestamp '),
 | |
|         synepoch.year,
 | |
|         synhtssep('-'),
 | |
|         synepoch.month,
 | |
|         synhtssep('-'),
 | |
|         synepoch.day,
 | |
|         synhtssep('T'),
 | |
|         synepoch.hour,
 | |
|         synhtssep(':'),
 | |
|         synepoch.minute,
 | |
|         synhtssep(':'),
 | |
|         synepoch.second,
 | |
|         h(':'),
 | |
|       },
 | |
|       {
 | |
|         c('  # Expected array of maps'),
 | |
|       },
 | |
|       {
 | |
|         { { 'ShaDaEntryRawMsgpack' }, '  = ' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' },
 | |
|         {
 | |
|           {
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackMap',
 | |
|             'ShaDaMsgpackBinaryString',
 | |
|             'ShaDaMsgpackStringQuotes',
 | |
|           },
 | |
|           '"',
 | |
|         },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'a' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, '+(' },
 | |
|         {
 | |
|           {
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackMap',
 | |
|             'ShaDaMsgpackExt',
 | |
|             'ShaDaMsgpackExtType',
 | |
|           },
 | |
|           '10',
 | |
|         },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, ')' },
 | |
|         {
 | |
|           {
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackMap',
 | |
|             'ShaDaMsgpackBinaryString',
 | |
|             'ShaDaMsgpackStringQuotes',
 | |
|           },
 | |
|           '"',
 | |
|         },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'ac' },
 | |
|         {
 | |
|           {
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackMap',
 | |
|             'ShaDaMsgpackBinaryString',
 | |
|             'ShaDaMsgpackBinaryStringEscape',
 | |
|           },
 | |
|           '\\0',
 | |
|         },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'df' },
 | |
|         {
 | |
|           {
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackMap',
 | |
|             'ShaDaMsgpackBinaryString',
 | |
|             'ShaDaMsgpackBinaryStringEscape',
 | |
|           },
 | |
|           '\\n',
 | |
|         },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'gi' },
 | |
|         {
 | |
|           {
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackMap',
 | |
|             'ShaDaMsgpackBinaryString',
 | |
|             'ShaDaMsgpackBinaryStringEscape',
 | |
|           },
 | |
|           '\\"',
 | |
|         },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'tt\\.' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackComma' }, ',' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'TRUE' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'FALSE' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMapBraces' }, '}' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' },
 | |
|         { { 'ShaDaMsgpackArray' }, ' ' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackKeyword' }, 'NIL' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray' }, ' ' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, '+(' },
 | |
|         {
 | |
|           {
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackExt',
 | |
|             'ShaDaMsgpackExtType',
 | |
|           },
 | |
|           '-10',
 | |
|         },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, ')' },
 | |
|         {
 | |
|           {
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackArray',
 | |
|             'ShaDaMsgpackBinaryString',
 | |
|             'ShaDaMsgpackStringQuotes',
 | |
|           },
 | |
|           '"',
 | |
|         },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' },
 | |
|         { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, ']' },
 | |
|         { { 'ShaDaMsgpackArrayBraces' }, ']' },
 | |
|       },
 | |
|       {
 | |
|         hname('Buffer list'),
 | |
|         h(' with timestamp '),
 | |
|         synepoch.year,
 | |
|         synhtssep('-'),
 | |
|         synepoch.month,
 | |
|         synhtssep('-'),
 | |
|         synepoch.day,
 | |
|         synhtssep('T'),
 | |
|         synepoch.hour,
 | |
|         synhtssep(':'),
 | |
|         synepoch.minute,
 | |
|         synhtssep(':'),
 | |
|         synepoch.second,
 | |
|         h(':'),
 | |
|       },
 | |
|       {
 | |
|         mlh('  % Key  Description  Value'),
 | |
|       },
 | |
|       {},
 | |
|       {
 | |
|         mlh('  % Key  Description  Value'),
 | |
|       },
 | |
|       {
 | |
|         hname('Header'),
 | |
|         h(' with timestamp '),
 | |
|         synepoch.year,
 | |
|         synhtssep('-'),
 | |
|         synepoch.month,
 | |
|         synhtssep('-'),
 | |
|         synepoch.day,
 | |
|         synhtssep('T'),
 | |
|         synepoch.hour,
 | |
|         synhtssep(':'),
 | |
|         synepoch.minute,
 | |
|         synhtssep(':'),
 | |
|         synepoch.second,
 | |
|         h(':'),
 | |
|       },
 | |
|       {
 | |
|         mlh('  % Key  Description________  Value'),
 | |
|       },
 | |
|       {
 | |
|         mles('  + '),
 | |
|         mlk('se   '),
 | |
|         mld('place cursor at end  '),
 | |
|         { { 'ShaDaEntryMapLong', 'ShaDaMsgpackKeyword' }, 'TRUE' },
 | |
|       },
 | |
|     }
 | |
|     eq(exp, act)
 | |
|   end)
 | |
| end)
 |