unittests: Fix automatic test case generation

This commit is contained in:
ZyX
2017-11-12 18:52:49 +03:00
parent 556451a7f2
commit 39c75d31be
2 changed files with 149 additions and 44 deletions

View File

@@ -310,6 +310,43 @@ local function mergedicts_copy(d1, d2)
return ret return ret
end end
-- dictdiff: find a diff so that mergedicts_copy(d1, diff) is equal to d2
--
-- Note: does not copy values from d2
local function dictdiff(d1, d2)
local ret = {}
local hasdiff = false
for k, v in pairs(d1) do
if d2[k] == nil then
hasdiff = true
ret[k] = REMOVE_THIS
elseif type(v) == type(d2[k]) then
if type(v) == 'table' and type(d2[k]) == 'table' then
local subdiff = dictdiff(v, d2[k])
if subdiff ~= nil then
hasdiff = true
ret[k] = subdiff
end
elseif v ~= d2[k] then
ret[k] = d2[k]
end
else
ret[k] = d2[k]
end
end
for k, v in pairs(d2) do
if d1[k] == nil then
ret[k] = v
hasdiff = true
end
end
if hasdiff then
return ret
else
return nil
end
end
local function updated(d, d2) local function updated(d, d2)
for k, v in pairs(d2) do for k, v in pairs(d2) do
d[k] = v d[k] = v
@@ -365,26 +402,37 @@ local SUBTBL = {
local format_luav local format_luav
format_luav = function(v, indent) format_luav = function(v, indent, opts)
opts = opts or {}
local linesep = '\n' local linesep = '\n'
local next_indent = nil local next_indent_arg = nil
if indent == nil then if indent == nil then
indent = '' indent = ''
linesep = '' linesep = ''
else else
next_indent = indent .. ' ' next_indent_arg = indent .. ' '
end end
local next_indent = indent .. ' '
local ret = '' local ret = ''
if type(v) == 'string' then if type(v) == 'string' then
ret = tostring(v):gsub('[\'\\]', '\\%0'):gsub('[%z\1-\31]', function(match) if opts.literal_strings then
ret = v
else
ret = tostring(v):gsub('[\'\\]', '\\%0'):gsub(
'[%z\1-\31]', function(match)
return SUBTBL[match:byte() + 1] return SUBTBL[match:byte() + 1]
end) end)
ret = '\'' .. ret .. '\'' ret = '\'' .. ret .. '\''
end
elseif type(v) == 'table' then elseif type(v) == 'table' then
if v == REMOVE_THIS then
ret = 'REMOVE_THIS'
else
local processed_keys = {} local processed_keys = {}
ret = '{' .. linesep ret = '{' .. linesep
for i, subv in ipairs(v) do for i, subv in ipairs(v) do
ret = ret .. (next_indent or '') .. format_luav(subv, next_indent) .. ',\n' ret = ('%s%s%s,\n'):format(ret, next_indent,
format_luav(subv, next_indent_arg, opts))
processed_keys[i] = true processed_keys[i] = true
end end
for k, subv in pairs(v) do for k, subv in pairs(v) do
@@ -392,12 +440,14 @@ format_luav = function(v, indent)
if type(k) == 'string' and k:match('^[a-zA-Z_][a-zA-Z0-9_]*$') then if type(k) == 'string' and k:match('^[a-zA-Z_][a-zA-Z0-9_]*$') then
ret = ret .. next_indent .. k .. ' = ' ret = ret .. next_indent .. k .. ' = '
else else
ret = ret .. next_indent .. '[' .. format_luav(k) .. '] = ' ret = ('%s%s[%s] = '):format(ret, next_indent,
format_luav(k, nil, opts))
end end
ret = ret .. format_luav(subv, next_indent) .. ',\n' ret = ret .. format_luav(subv, next_indent_arg, opts) .. ',\n'
end end
end end
ret = ret .. indent .. '}' ret = ret .. indent .. '}'
end
elseif type(v) == 'number' then elseif type(v) == 'number' then
if v % 1 == 0 then if v % 1 == 0 then
ret = ('%d'):format(v) ret = ('%d'):format(v)
@@ -461,6 +511,7 @@ return {
shallowcopy = shallowcopy, shallowcopy = shallowcopy,
deepcopy = deepcopy, deepcopy = deepcopy,
mergedicts_copy = mergedicts_copy, mergedicts_copy = mergedicts_copy,
dictdiff = dictdiff,
REMOVE_THIS = REMOVE_THIS, REMOVE_THIS = REMOVE_THIS,
concat_tables = concat_tables, concat_tables = concat_tables,
dedent = dedent, dedent = dedent,

View File

@@ -27,6 +27,7 @@ local format_string = global_helpers.format_string
local format_luav = global_helpers.format_luav local format_luav = global_helpers.format_luav
local intchar2lua = global_helpers.intchar2lua local intchar2lua = global_helpers.intchar2lua
local REMOVE_THIS = global_helpers.REMOVE_THIS local REMOVE_THIS = global_helpers.REMOVE_THIS
local dictdiff = global_helpers.dictdiff
local lib = cimport('./src/nvim/viml/parser/expressions.h', local lib = cimport('./src/nvim/viml/parser/expressions.h',
'./src/nvim/syntax.h') './src/nvim/syntax.h')
@@ -180,9 +181,31 @@ child_call_once(function()
end end
end) end)
local function format_check(expr, flags, ast, hls) local function hls_to_hl_fs(hls)
local ret = {}
local next_col = 0
for i, v in ipairs(hls) do
local group, line, col, str = v:match('^NVim([a-zA-Z]+):(%d+):(%d+):(.*)$')
col = tonumber(col)
line = tonumber(line)
assert(line == 0)
local col_shift = col - next_col
assert(col_shift >= 0)
next_col = col + #str
ret[i] = format_string('hl(%r, %r%s)',
group,
str,
(col_shift == 0
and ''
or (', %u'):format(col_shift)))
end
return ret
end
local function format_check(expr, format_check_data)
-- That forces specific order. -- That forces specific order.
print( format_string('\ncheck_parsing(%r, %u, {', expr, flags)) local zdata = format_check_data[0]
print(format_string('\ncheck_parsing(%r, {', expr, flags))
local digits = ' -- ' local digits = ' -- '
local digits2 = ' -- ' local digits2 = ' -- '
for i = 0, #expr - 1 do for i = 0, #expr - 1 do
@@ -195,27 +218,56 @@ local function format_check(expr, flags, ast, hls)
if #expr > 10 then if #expr > 10 then
print(digits2) print(digits2)
end end
print(' ast = ' .. format_luav(ast.ast, ' ') .. ',') print(' ast = ' .. format_luav(zdata.ast.ast, ' ') .. ',')
if ast.err then if zdata.ast.err then
print(' err = {') print(' err = {')
print(' arg = ' .. format_luav(ast.err.arg) .. ',') print(' arg = ' .. format_luav(zdata.ast.err.arg) .. ',')
print(' msg = ' .. format_luav(ast.err.msg) .. ',') print(' msg = ' .. format_luav(zdata.ast.err.msg) .. ',')
print(' },') print(' },')
end end
print('}, {') print('}, {')
local next_col = 0 for _, v in ipairs(zdata.hl_fs) do
for _, v in ipairs(hls) do print(' ' .. v .. ',')
local group, line, col, str = v:match('NVim([a-zA-Z]+):(%d+):(%d+):(.*)') end
col = tonumber(col) local diffs = {}
line = tonumber(line) local diffs_num = 0
assert(line == 0) for flags, v in pairs(format_check_data) do
local col_shift = col - next_col if flags ~= 0 then
assert(col_shift >= 0) diffs[flags] = dictdiff(zdata, v)
next_col = col + #str if diffs[flags] then
print(format_string(' hl(%r, %r%s),', if flags == 3 then
group, if (dictdiff(format_check_data[1], format_check_data[3]) == nil
str, or dictdiff(format_check_data[2], format_check_data[3]) == nil) then
(col_shift == 0 and '' or (', %u'):format(col_shift)))) diffs[flags] = nil
else
diffs_num = diffs_num + 1
end
else
diffs_num = diffs_num + 1
end
end
end
end
if diffs_num ~= 0 then
print('}, {')
local flags = 1
while diffs_num ~= 0 do
if diffs[flags] then
diffs_num = diffs_num - 1
local diff = diffs[flags]
print((' [%u] = {'):format(flags))
if diff.ast then
print(' ast = ' .. format_luav(diff.ast, ' '))
end
if diff.hl_fs then
print(' hl_fs = ' .. format_luav(diff.hl_fs, ' ', {
literal_strings=true
}))
end
print(' },')
end
flags = flags + 1
end
end end
print('})') print('})')
end end
@@ -387,8 +439,7 @@ end)
describe('Expressions parser', function() describe('Expressions parser', function()
local function check_parsing(str, exp_ast, exp_highlighting_fs, nz_flags_exps) local function check_parsing(str, exp_ast, exp_highlighting_fs, nz_flags_exps)
nz_flags_exps = nz_flags_exps or {} nz_flags_exps = nz_flags_exps or {}
local format_check_data = function() local format_check_data = {}
end
for _, flags in ipairs({0, 1, 2, 3}) do for _, flags in ipairs({0, 1, 2, 3}) do
debug_log(('Running test case (%s, %u)'):format(str, flags)) debug_log(('Running test case (%s, %u)'):format(str, flags))
local err, msg = pcall(function() local err, msg = pcall(function()
@@ -418,7 +469,7 @@ describe('Expressions parser', function()
end end
end end
if exp_ast == nil then if exp_ast == nil then
format_check(str, ast, hls) format_check_data[flags] = {ast=ast, hl_fs=hls_to_hl_fs(hls)}
else else
eq(exps.ast, ast) eq(exps.ast, ast)
if exp_highlighting_fs then if exp_highlighting_fs then
@@ -441,6 +492,9 @@ describe('Expressions parser', function()
error(msg) error(msg)
end end
end end
if exp_ast == nil then
format_check(str, format_check_data)
end
end end
local function hl(group, str, shift) local function hl(group, str, shift)
return function(next_col) return function(next_col)