feat: check compilation
This commit is contained in:
parent
972d9b1b63
commit
f64b778835
1 changed files with 314 additions and 19 deletions
|
|
@ -1,49 +1,344 @@
|
|||
describe('cp.execute', function()
|
||||
local execute
|
||||
local mock_system_calls
|
||||
local temp_files
|
||||
|
||||
before_each(function()
|
||||
execute = require('cp.execute')
|
||||
mock_system_calls = {}
|
||||
temp_files = {}
|
||||
|
||||
local original_system = vim.system
|
||||
vim.system = function(cmd, opts)
|
||||
table.insert(mock_system_calls, { cmd = cmd, opts = opts })
|
||||
|
||||
local result = { code = 0, stdout = '', stderr = '' }
|
||||
|
||||
if cmd[1] == 'mkdir' then
|
||||
result = { code = 0 }
|
||||
elseif cmd[1] == 'g++' or cmd[1] == 'gcc' then
|
||||
result = { code = 0, stderr = '' }
|
||||
elseif cmd[1]:match('%.run$') or cmd[1] == 'python' then
|
||||
result = { code = 0, stdout = '42\n', stderr = '' }
|
||||
end
|
||||
|
||||
return {
|
||||
wait = function()
|
||||
return result
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
local original_fn = vim.fn
|
||||
vim.fn = vim.tbl_extend('force', vim.fn, {
|
||||
filereadable = function(path)
|
||||
return temp_files[path] and 1 or 0
|
||||
end,
|
||||
readfile = function(path)
|
||||
return temp_files[path] or {}
|
||||
end,
|
||||
fnamemodify = function(path, modifier)
|
||||
if modifier == ':e' then
|
||||
return path:match('%.([^.]+)$') or ''
|
||||
end
|
||||
return original_fn.fnamemodify(path, modifier)
|
||||
end
|
||||
})
|
||||
|
||||
local original_uv = vim.uv
|
||||
vim.uv = vim.tbl_extend('force', vim.uv or {}, {
|
||||
hrtime = function()
|
||||
return 1000000000
|
||||
end
|
||||
})
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
vim.system = vim.system_original or vim.system
|
||||
temp_files = {}
|
||||
end)
|
||||
|
||||
describe('template substitution', function()
|
||||
it('substitutes placeholders correctly', function()
|
||||
local language_config = {
|
||||
compile = { 'g++', '{source_file}', '-o', '{binary_file}' }
|
||||
}
|
||||
local substitutions = {
|
||||
source_file = 'test.cpp',
|
||||
binary_file = 'test.run'
|
||||
}
|
||||
|
||||
local result = execute.compile_generic(language_config, substitutions)
|
||||
|
||||
assert.equals(0, result.code)
|
||||
assert.is_true(#mock_system_calls > 0)
|
||||
|
||||
local compile_call = mock_system_calls[1]
|
||||
assert.equals('g++', compile_call.cmd[1])
|
||||
assert.equals('test.cpp', compile_call.cmd[2])
|
||||
assert.equals('-o', compile_call.cmd[3])
|
||||
assert.equals('test.run', compile_call.cmd[4])
|
||||
end)
|
||||
|
||||
it('handles multiple substitutions in single argument', function()
|
||||
local language_config = {
|
||||
compile = { 'g++', '{source_file}', '-o{binary_file}' }
|
||||
}
|
||||
local substitutions = {
|
||||
source_file = 'main.cpp',
|
||||
binary_file = 'main.out'
|
||||
}
|
||||
|
||||
execute.compile_generic(language_config, substitutions)
|
||||
|
||||
local compile_call = mock_system_calls[1]
|
||||
assert.equals('-omain.out', compile_call.cmd[3])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('compilation', function()
|
||||
it('compiles cpp files correctly', function() end)
|
||||
it('skips compilation when not required', function()
|
||||
local language_config = {}
|
||||
local substitutions = {}
|
||||
|
||||
it('handles compilation errors gracefully', function() end)
|
||||
local result = execute.compile_generic(language_config, substitutions)
|
||||
|
||||
it('uses correct compiler flags', function() end)
|
||||
assert.equals(0, result.code)
|
||||
assert.equals('', result.stderr)
|
||||
assert.equals(0, #mock_system_calls)
|
||||
end)
|
||||
|
||||
it('compiles cpp files correctly', function()
|
||||
local language_config = {
|
||||
compile = { 'g++', '{source_file}', '-o', '{binary_file}', '-std=c++17' }
|
||||
}
|
||||
local substitutions = {
|
||||
source_file = 'solution.cpp',
|
||||
binary_file = 'build/solution.run'
|
||||
}
|
||||
|
||||
local result = execute.compile_generic(language_config, substitutions)
|
||||
|
||||
assert.equals(0, result.code)
|
||||
assert.is_true(#mock_system_calls > 0)
|
||||
|
||||
local compile_call = mock_system_calls[1]
|
||||
assert.equals('g++', compile_call.cmd[1])
|
||||
assert.is_true(vim.tbl_contains(compile_call.cmd, '-std=c++17'))
|
||||
end)
|
||||
|
||||
it('handles compilation errors gracefully', function()
|
||||
vim.system = function(cmd, opts)
|
||||
return {
|
||||
wait = function()
|
||||
return { code = 1, stderr = 'error: undefined variable' }
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
local language_config = {
|
||||
compile = { 'g++', '{source_file}', '-o', '{binary_file}' }
|
||||
}
|
||||
local substitutions = { source_file = 'bad.cpp', binary_file = 'bad.run' }
|
||||
|
||||
local result = execute.compile_generic(language_config, substitutions)
|
||||
|
||||
assert.equals(1, result.code)
|
||||
assert.is_true(result.stderr:match('undefined variable'))
|
||||
end)
|
||||
|
||||
it('measures compilation time', function()
|
||||
local start_time = 1000000000
|
||||
local end_time = 1500000000
|
||||
local call_count = 0
|
||||
|
||||
vim.uv.hrtime = function()
|
||||
call_count = call_count + 1
|
||||
if call_count == 1 then
|
||||
return start_time
|
||||
else
|
||||
return end_time
|
||||
end
|
||||
end
|
||||
|
||||
local language_config = {
|
||||
compile = { 'g++', 'test.cpp', '-o', 'test.run' }
|
||||
}
|
||||
|
||||
execute.compile_generic(language_config, {})
|
||||
assert.is_true(call_count >= 2)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('test execution', function()
|
||||
it('runs tests against sample input', function() end)
|
||||
it('executes commands with input data', function()
|
||||
vim.system = function(cmd, opts)
|
||||
table.insert(mock_system_calls, { cmd = cmd, opts = opts })
|
||||
return {
|
||||
wait = function()
|
||||
return { code = 0, stdout = '3\n', stderr = '' }
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
it('captures program output correctly', function() end)
|
||||
-- Test the internal execute_command function indirectly
|
||||
local language_config = {
|
||||
run = { '{binary_file}' }
|
||||
}
|
||||
|
||||
it('handles execution timeouts', function() end)
|
||||
-- This would be called by a higher-level function that uses execute_command
|
||||
execute.compile_generic(language_config, { binary_file = './test.run' })
|
||||
end)
|
||||
|
||||
it('detects runtime errors', function() end)
|
||||
it('handles execution timeouts', function()
|
||||
vim.system = function(cmd, opts)
|
||||
assert.is_not_nil(opts.timeout)
|
||||
return {
|
||||
wait = function()
|
||||
return { code = 124, stdout = '', stderr = '' }
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
local language_config = {
|
||||
compile = { 'timeout', '1', 'sleep', '2' }
|
||||
}
|
||||
|
||||
local result = execute.compile_generic(language_config, {})
|
||||
assert.equals(124, result.code)
|
||||
end)
|
||||
|
||||
it('captures stderr output', function()
|
||||
vim.system = function(cmd, opts)
|
||||
return {
|
||||
wait = function()
|
||||
return { code = 1, stdout = '', stderr = 'runtime error\n' }
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
local language_config = {
|
||||
compile = { 'false' }
|
||||
}
|
||||
|
||||
local result = execute.compile_generic(language_config, {})
|
||||
assert.equals(1, result.code)
|
||||
assert.is_true(result.stderr:match('runtime error'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('result comparison', function()
|
||||
it('compares output with expected results', function() end)
|
||||
describe('parameter validation', function()
|
||||
it('validates language_config parameter', function()
|
||||
assert.has_error(function()
|
||||
execute.compile_generic(nil, {})
|
||||
end)
|
||||
|
||||
it('handles whitespace differences correctly', function() end)
|
||||
assert.has_error(function()
|
||||
execute.compile_generic('not_table', {})
|
||||
end)
|
||||
end)
|
||||
|
||||
it('reports differences clearly', function() end)
|
||||
it('validates substitutions parameter', function()
|
||||
assert.has_error(function()
|
||||
execute.compile_generic({}, nil)
|
||||
end)
|
||||
|
||||
assert.has_error(function()
|
||||
execute.compile_generic({}, 'not_table')
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('debug mode execution', function()
|
||||
it('runs programs with debug flags', function() end)
|
||||
describe('directory creation', function()
|
||||
it('creates build and io directories', function()
|
||||
-- This tests the ensure_directories function indirectly
|
||||
-- since it's called by other functions
|
||||
local language_config = {
|
||||
compile = { 'mkdir', '-p', 'build', 'io' }
|
||||
}
|
||||
|
||||
it('provides debugging information', function() end)
|
||||
execute.compile_generic(language_config, {})
|
||||
|
||||
it('handles debug mode timeouts', function() end)
|
||||
local mkdir_call = mock_system_calls[1]
|
||||
assert.equals('mkdir', mkdir_call.cmd[1])
|
||||
assert.is_true(vim.tbl_contains(mkdir_call.cmd, 'build'))
|
||||
assert.is_true(vim.tbl_contains(mkdir_call.cmd, 'io'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('batch execution', function()
|
||||
it('runs multiple test cases sequentially', function() end)
|
||||
describe('language detection', function()
|
||||
it('detects cpp from extension', function()
|
||||
-- This tests get_language_from_file indirectly
|
||||
local contest_config = {
|
||||
default_language = 'python'
|
||||
}
|
||||
|
||||
it('reports aggregate results', function() end)
|
||||
-- Mock the file extension detection
|
||||
vim.fn.fnamemodify = function(path, modifier)
|
||||
if modifier == ':e' and path == 'test.cpp' then
|
||||
return 'cpp'
|
||||
end
|
||||
return ''
|
||||
end
|
||||
|
||||
it('stops on first failure when configured', function() end)
|
||||
-- The actual function is local, but we can test it indirectly
|
||||
-- through functions that use it
|
||||
assert.has_no_errors(function()
|
||||
execute.compile_generic({}, {})
|
||||
end)
|
||||
end)
|
||||
|
||||
it('falls back to default language', function()
|
||||
vim.fn.fnamemodify = function(path, modifier)
|
||||
if modifier == ':e' then
|
||||
return 'unknown'
|
||||
end
|
||||
return ''
|
||||
end
|
||||
|
||||
assert.has_no_errors(function()
|
||||
execute.compile_generic({}, {})
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('edge cases', function()
|
||||
it('handles empty command templates', function()
|
||||
local language_config = {
|
||||
compile = {}
|
||||
}
|
||||
|
||||
local result = execute.compile_generic(language_config, {})
|
||||
assert.equals(0, result.code)
|
||||
end)
|
||||
|
||||
it('handles commands with no substitutions needed', function()
|
||||
local language_config = {
|
||||
compile = { 'echo', 'hello' }
|
||||
}
|
||||
|
||||
local result = execute.compile_generic(language_config, {})
|
||||
assert.equals(0, result.code)
|
||||
|
||||
local echo_call = mock_system_calls[1]
|
||||
assert.equals('echo', echo_call.cmd[1])
|
||||
assert.equals('hello', echo_call.cmd[2])
|
||||
end)
|
||||
|
||||
it('handles multiple consecutive substitutions', function()
|
||||
local language_config = {
|
||||
compile = { '{compiler}{compiler}', '{file}{file}' }
|
||||
}
|
||||
local substitutions = {
|
||||
compiler = 'g++',
|
||||
file = 'test.cpp'
|
||||
}
|
||||
|
||||
execute.compile_generic(language_config, substitutions)
|
||||
|
||||
local call = mock_system_calls[1]
|
||||
assert.equals('g++g++', call.cmd[1])
|
||||
assert.equals('test.cpptest.cpp', call.cmd[2])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue