You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
3.9 KiB
Lua

--- Module which contains the main logic of the CLI application
-- @module lqc.cli.app
-- @alias app
local Vector = require 'lqc.helpers.vector'
local reduce = require 'lqc.helpers.reduce'
local filter = require 'lqc.helpers.filter'
local fs = require 'lqc.helpers.fs'
local random = require 'lqc.random'
local lqc = require 'lqc.quickcheck'
local loader = require 'lqc.cli.loader'
local arg_parser = require 'lqc.cli.arg_parser'
local report = require 'lqc.report'
-- File used for remembering last used seed for generating test cases.
local check_file = '.lqc'
--- Tries to read the last quickcheck seed.
-- @return the last used seed (or nil on error).
local function read_from_check_file()
return fs.read_file(check_file)
end
--- Writes the seed to the check file (.lqc.lua).
-- @param seed Seed to write to the file
local function write_to_check_file(seed)
fs.write_file(check_file, seed)
end
--- Initializes the random seed; either with last used value (--check) or a
-- specific seed (-s, --seed) or default (current timestamp)
-- @param config Config which specifies how seed initialization should be handled
local function initialize_random_seed(config)
local seed = config.seed
if config.check then -- redo last generated test run (if --check specified)
seed = read_from_check_file()
end
local actual_used_seed = random.seed(seed)
write_to_check_file(actual_used_seed)
report.report_seed(actual_used_seed)
end
--- Depending on the config, returns a list of files that should be executed.
-- @return List of script files that should be executed.
local function find_files(files_or_dirs)
return reduce(files_or_dirs, Vector.new(), function(file_or_dir, acc)
if fs.is_file(file_or_dir) then
return acc:push_back(file_or_dir)
end
-- directory
return acc:append(Vector.new(fs.find_files(file_or_dir)))
end):to_table()
end
--- Checks if a file is a file ending in .lua or .moon (if moonscript available)
-- @param file Path to a file
-- @return true if it has the correct extension; otherwise false.
local function is_script_file(file)
return fs.is_lua_file(file) or fs.is_moonscript_file(file)
end
--- Filters out all files not ending in .lua or .moon
-- @param files list of all files
-- @return filtered list of files, containing only the Lua and Moonscript scripts
local function find_script_files(files)
return filter(files, is_script_file)
end
--- Executes all scripts, specified by a table of file paths.
-- @param files List of scripts to execute.
local function execute_scripts(files)
for _, file in pairs(files) do
-- TODO clear environment each time?
local script = loader.load_script(file)
script()
end
end
--- Verifies all properties, with the work divided over X number of threads.
-- @param numthreads Number of threads to divide the work over.
local function verify_properties(numthreads)
if numthreads == 1 then
lqc.check()
return
end
lqc.check_mt(numthreads)
end
--- Shows the test output (statistics)
local function show_output()
report.report_errors()
report.report_summary()
end
local app = {}
-- Exits the application
function app.exit()
os.exit(lqc.failed and 1 or 0)
end
--- Main function of the CLI application
-- 1. parse arguments
-- 2. find all files needed to run
-- 3. initialize random seed
-- 4. run 1 file, or all files in a directory (depending on args)
-- 5. execute properties (lqc.check)
-- 6. show output
-- @param cli_args Table containing the commandline arguments
function app.main(cli_args)
local config = arg_parser.parse(cli_args or {})
local files = find_files(config.files_or_dirs)
local script_files = find_script_files(files)
initialize_random_seed(config)
lqc.init(config.numtests, config.numshrinks)
report.configure(config.colors)
execute_scripts(script_files)
verify_properties(config.threads)
show_output()
app.exit()
end
return app