--- Module which contains the core of the quickcheck engine. -- @module lqc.quickcheck -- @alias lib local report = require 'lqc.report' local map = require 'lqc.helpers.map' local shuffle = pairs local lib = { properties = {}, -- list of all properties numtests = nil, -- Default amount of times a property should be tested numshrinks = nil, -- Default amount of times a failing property should be shrunk down failed = false, } --- Checks if the quickcheck configuration is initialized -- @return true if it is initialized; otherwise false. local function is_initialized() return lib.numtests ~= nil and lib.numshrinks ~= nil end --- Handles the result of a property. -- @param result table containing information of the property (or nil on success) -- @see lqc.property_result local function handle_result(result) if not result then return end -- successful lib.failed = true if type(result.property) == 'table' then -- property failed report.report_failed_property(result.property, result.generated_values, result.shrunk_values) return end -- FSM failed report.report_failed_fsm(result.description, result.generated_values, result.shrunk_values) end --- Configures the amount of iterations and shrinks the check algorithm should perform. -- @param numtests Default number of tests per property -- @param numshrinks Default number of shrinks per property function lib.init(numtests, numshrinks) lib.numtests = numtests lib.numshrinks = numshrinks end --- Iterates over all properties in a random order and checks if the property -- holds true for each generated set of inputs. Raises an error if quickcheck -- engine is not initialized yet. function lib.check() if not is_initialized() then error 'quickcheck.init() has to be called before quickcheck.check()!' end for _, prop in shuffle(lib.properties) do local result = prop:check() handle_result(result) end end --- Multithreaded version of check(), uses a thread pool in the underlying -- implementation. Splits up the properties over different threads. -- @param numthreads Number of the threads to divide the properties over. function lib.check_mt(numthreads) local ThreadPool = require 'lqc.threading.thread_pool' if not is_initialized() then error 'quickcheck.init() has to be called before quickcheck.check_mt()!' end local pool = ThreadPool.new(numthreads) for _, prop in shuffle(lib.properties) do pool:schedule(function() return prop:check() end) end local results = pool:join() map(results, handle_result) end return lib