neovim/test/functional/plugin/shada_spec.lua
bfredl bda63d5b97 refactor(typval)!: remove distinction of binary and nonbinary strings
This is a breaking change which will make refactor of typval and shada
code a lot easier. In particular, code that would use or check for
v:msgpack_types.binary in the wild would be broken. This appears to be
rarely used in existing plugins.

Also some cases where v:msgpack_type.string would be used to represent a
binary string of "string" type, we use a BLOB instead, which is
vimscripts native type for binary blobs, and already was used for BIN
formats when necessary.

msgpackdump(msgpackparse(data)) no longer preserves the distinction
of BIN and STR strings. This is very common behavior for
language-specific msgpack bindings. Nvim uses msgpack as a tool to
serialize its data. Nvim is not a tool to bit-perfectly manipulate
arbitrary msgpack data out in the wild.

The changed tests should indicate how behavior changes in various edge
cases.
2024-06-27 11:04:04 +02:00

3619 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 },
}
screen:attach()
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)