mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-03 17:24:29 +00:00 
			
		
		
		
	Before calling "attach" a screen object is just a dummy container for (row, col) values whose purpose is to be sent as part of the "attach" function call anyway. Just create the screen in an attached state directly. Keep the complete (row, col, options) config together. It is still completely valid to later detach and re-attach as needed, including to another session.
		
			
				
	
	
		
			3618 lines
		
	
	
		
			115 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			3618 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)
 | 
						|
  before_each(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 = 'ShaDaCommands', 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', {}))
 | 
						|
    eq('++opt not supported', exc_exec('edit ++enc=latin1 ' .. fname))
 | 
						|
    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, {})
 | 
						|
    eq('++opt not supported', exc_exec('$read ++enc=latin1 ' .. fname))
 | 
						|
    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)
 | 
						|
    eq('++opt not supported', exc_exec('w! ++enc=latin1 ' .. fname))
 | 
						|
    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)
 | 
						|
    eq('++opt not supported', exc_exec('1,3w! ++enc=latin1 ' .. fname))
 | 
						|
    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)
 | 
						|
    eq('++opt not supported', exc_exec('1,3w! ++enc=latin1 >> ' .. fname))
 | 
						|
    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)
 |