refactor(api): VALIDATE macros #22187

Problem:
- API validation involves too much boilerplate.
- API validation errors are not consistently worded.

Solution:
Introduce some macros. Currently these are clumsy, but they at least
help with consistency and avoid some nesting.
This commit is contained in:
Justin M. Keyes
2023-02-14 05:19:04 -05:00
committed by GitHub
parent 5396808267
commit 46a87a5d2b
17 changed files with 592 additions and 634 deletions

View File

@@ -21,7 +21,7 @@ describe('autocmd api', function()
callback = "NotAllowed",
})
eq("specify either 'callback' or 'command', not both", rv)
eq("Cannot use both 'callback' and 'command'", rv)
end)
it('doesnt leak when you use ++once', function()
@@ -66,7 +66,7 @@ describe('autocmd api', function()
pattern = "*.py",
})
eq("cannot pass both: 'pattern' and 'buffer' for the same autocmd", rv)
eq("Cannot use both 'pattern' and 'buffer' for the same autocmd", rv)
end)
it('does not allow passing invalid buffers', function()
@@ -407,8 +407,8 @@ describe('autocmd api', function()
pattern = "<buffer=2>",
}}, aus)
eq("Invalid value for 'buffer': must be an integer or array of integers", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = "foo" }))
eq("Invalid value for 'buffer': must be an integer", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { "foo", 42 } }))
eq("Invalid buffer: expected Integer or Array, got String", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = "foo" }))
eq("Invalid buffer: expected Integer, got String", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { "foo", 42 } }))
eq("Invalid buffer id: 42", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { 42 } }))
local bufs = {}
@@ -416,7 +416,7 @@ describe('autocmd api', function()
table.insert(bufs, meths.create_buf(true, false))
end
eq("Too many buffers. Please limit yourself to 256 or fewer", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = bufs }))
eq("Too many buffers (maximum of 256)", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = bufs }))
end)
it('should return autocmds when group is specified by id', function()
@@ -578,7 +578,7 @@ describe('autocmd api', function()
]], {}))
eq(false, success)
matches('invalid augroup: NotDefined', code)
matches("Invalid group: 'NotDefined'", code)
end)
it('raises error for undefined augroup id', function()
@@ -596,7 +596,7 @@ describe('autocmd api', function()
]], {}))
eq(false, success)
matches('invalid augroup: 1', code)
matches('Invalid group: 1', code)
end)
it('raises error for invalid group type', function()
@@ -611,7 +611,7 @@ describe('autocmd api', function()
]], {}))
eq(false, success)
matches("'group' must be a string or an integer", code)
matches("Invalid group: expected String or Integer, got Boolean", code)
end)
it('raises error for invalid pattern array', function()
@@ -625,7 +625,7 @@ describe('autocmd api', function()
]], {}))
eq(false, success)
matches("All entries in 'pattern' must be strings", code)
matches("Invalid 'pattern' item type: expected String, got Array", code)
end)
end)

View File

@@ -762,7 +762,7 @@ describe('API: buffer events:', function()
it('returns a proper error on nonempty options dict', function()
clear()
local b = editoriginal(false)
eq("unexpected key: builtin", pcall_err(buffer, 'attach', b, false, {builtin="asfd"}))
eq("Invalid key: 'builtin'", pcall_err(buffer, 'attach', b, false, {builtin="asfd"}))
end)
it('nvim_buf_attach returns response after delay #8634', function()

View File

@@ -543,7 +543,7 @@ describe('nvim_create_user_command', function()
end)
it('does not allow invalid command names', function()
matches("'name' must begin with an uppercase letter", pcall_err(exec_lua, [[
matches("Invalid command name %(must begin with an uppercase letter%): 'test'", pcall_err(exec_lua, [[
vim.api.nvim_create_user_command('test', 'echo "hi"', {})
]]))

View File

@@ -106,7 +106,7 @@ describe('API/extmarks', function()
end_col = 0,
end_row = 1
})
eq("end_col value outside range",
eq("Invalid end_col: '(out of range)'",
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 }))
end)
@@ -1344,10 +1344,10 @@ describe('API/extmarks', function()
it('throws consistent error codes', function()
local ns_invalid = ns2 + 1
eq("Invalid ns_id", pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2]))
eq("Invalid ns_id", pcall_err(curbufmeths.del_extmark, ns_invalid, marks[1]))
eq("Invalid ns_id", pcall_err(get_extmarks, ns_invalid, positions[1], positions[2]))
eq("Invalid ns_id", pcall_err(get_extmark_by_id, ns_invalid, marks[1]))
eq("Invalid ns_id: 3", pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2]))
eq("Invalid ns_id: 3", pcall_err(curbufmeths.del_extmark, ns_invalid, marks[1]))
eq("Invalid ns_id: 3", pcall_err(get_extmarks, ns_invalid, positions[1], positions[2]))
eq("Invalid ns_id: 3", pcall_err(get_extmark_by_id, ns_invalid, marks[1]))
end)
it('when col = line-length, set the mark on eol', function()
@@ -1362,13 +1362,13 @@ describe('API/extmarks', function()
it('when col = line-length, set the mark on eol', function()
local invalid_col = init_text:len() + 1
eq("col value outside range", pcall_err(set_extmark, ns, marks[1], 0, invalid_col))
eq("Invalid col: '(out of range)'", pcall_err(set_extmark, ns, marks[1], 0, invalid_col))
end)
it('fails when line > line_count', function()
local invalid_col = init_text:len() + 1
local invalid_lnum = 3
eq('line value outside range', pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col))
eq("Invalid line: '(out of range)'", pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col))
eq({}, get_extmark_by_id(ns, marks[1]))
end)

View File

@@ -1155,7 +1155,7 @@ describe('API', function()
describe('nvim_put', function()
it('validates args', function()
eq('Invalid lines (expected array of strings)',
eq("Invalid line: expected String, got Integer",
pcall_err(request, 'nvim_put', {42}, 'l', false, false))
eq("Invalid type: 'x'",
pcall_err(request, 'nvim_put', {'foo'}, 'x', false, false))
@@ -1410,6 +1410,15 @@ describe('API', function()
ok(not nvim('get_option_value', 'equalalways', {}))
end)
it('validation', function()
eq("Invalid scope (expected 'local' or 'global')",
pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 'bogus'}))
eq("Invalid scope (expected 'local' or 'global')",
pcall_err(nvim, 'set_option_value', 'scrolloff', 1, {scope = 'bogus'}))
eq("Invalid scope: expected String, got Integer",
pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 42}))
end)
it('can get local values when global value is set', function()
eq(0, nvim('get_option_value', 'scrolloff', {}))
eq(-1, nvim('get_option_value', 'scrolloff', {scope = 'local'}))
@@ -1780,9 +1789,9 @@ describe('API', function()
it('validates args', function()
eq("Invalid key: 'blah'",
pcall_err(nvim, 'get_context', {blah={}}))
eq('invalid value for key: types',
eq("Invalid types: expected Array, got Integer",
pcall_err(nvim, 'get_context', {types=42}))
eq('unexpected type: zub',
eq("Invalid type: 'zub'",
pcall_err(nvim, 'get_context', {types={'jumps', 'zub', 'zam',}}))
end)
it('returns map of current editor state', function()
@@ -2223,15 +2232,14 @@ describe('API', function()
eq(5, meths.get_var('avar'))
end)
it('throws error on malformed arguments', function()
it('validation', function()
local req = {
{'nvim_set_var', {'avar', 1}},
{'nvim_set_var'},
{'nvim_set_var', {'avar', 2}},
}
local status, err = pcall(meths.call_atomic, req)
eq(false, status)
ok(err:match('Items in calls array must be arrays of size 2') ~= nil)
eq('Items in calls array must be arrays of size 2',
pcall_err(meths.call_atomic, req))
-- call before was done, but not after
eq(1, meths.get_var('avar'))
@@ -2239,18 +2247,16 @@ describe('API', function()
{ 'nvim_set_var', { 'bvar', { 2, 3 } } },
12,
}
status, err = pcall(meths.call_atomic, req)
eq(false, status)
ok(err:match('Items in calls array must be arrays') ~= nil)
eq("Invalid calls item: expected Array, got Integer",
pcall_err(meths.call_atomic, req))
eq({2,3}, meths.get_var('bvar'))
req = {
{'nvim_set_current_line', 'little line'},
{'nvim_set_var', {'avar', 3}},
}
status, err = pcall(meths.call_atomic, req)
eq(false, status)
ok(err:match('Args must be Array') ~= nil)
eq("Invalid args: expected Array, got String",
pcall_err(meths.call_atomic, req))
-- call before was done, but not after
eq(1, meths.get_var('avar'))
eq({''}, meths.buf_get_lines(0, 0, -1, true))
@@ -2750,7 +2756,7 @@ describe('API', function()
describe('nvim_get_option_info', function()
it('should error for unknown options', function()
eq("no such option: 'bogus'", pcall_err(meths.get_option_info, 'bogus'))
eq("Invalid option (not found): 'bogus'", pcall_err(meths.get_option_info, 'bogus'))
end)
it('should return the same options for short and long name', function()
@@ -3031,10 +3037,10 @@ describe('API', function()
eq(true, meths.del_mark('F'))
eq({0, 0}, meths.buf_get_mark(buf, 'F'))
end)
it('fails when invalid marks are used', function()
eq(false, pcall(meths.del_mark, 'f'))
eq(false, pcall(meths.del_mark, '!'))
eq(false, pcall(meths.del_mark, 'fail'))
it('validation', function()
eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(meths.del_mark, 'f'))
eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(meths.del_mark, '!'))
eq("Invalid mark name (must be a single char): 'fail'", pcall_err(meths.del_mark, 'fail'))
end)
end)
describe('nvim_get_mark', function()
@@ -3048,10 +3054,10 @@ describe('API', function()
assert(string.find(mark[4], "mybuf$"))
eq({2, 2, buf.id, mark[4]}, mark)
end)
it('fails when invalid marks are used', function()
eq(false, pcall(meths.del_mark, 'f'))
eq(false, pcall(meths.del_mark, '!'))
eq(false, pcall(meths.del_mark, 'fail'))
it('validation', function()
eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(meths.get_mark, 'f', {}))
eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(meths.get_mark, '!', {}))
eq("Invalid mark name (must be a single char): 'fail'", pcall_err(meths.get_mark, 'fail', {}))
end)
it('returns the expected when mark is not set', function()
eq(true, meths.del_mark('A'))
@@ -3113,15 +3119,15 @@ describe('API', function()
meths.eval_statusline('a%=b', { fillchar = '\031', maxwidth = 5 }))
end)
it('rejects multiple-character fillchar', function()
eq('fillchar must be a single character',
eq('Invalid fillchar (not a single character)',
pcall_err(meths.eval_statusline, '', { fillchar = 'aa' }))
end)
it('rejects empty string fillchar', function()
eq('fillchar must be a single character',
eq('Invalid fillchar (not a single character)',
pcall_err(meths.eval_statusline, '', { fillchar = '' }))
end)
it('rejects non-string fillchar', function()
eq('fillchar must be a single character',
eq("Invalid fillchar: expected String, got Integer",
pcall_err(meths.eval_statusline, '', { fillchar = 1 }))
end)
it('rejects invalid string', function()