Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 28 additions & 16 deletions .github/workflows/tests-and-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ jobs:
os: [linux, macos, macos-arm64]
lua: [lua=5.1, lua=5.2, lua=5.3, lua=5.4, luajit=@v2.0, luajit=@v2.1]
include:
- os: linux
runner: ubuntu-latest
- os: macos
runner: macos-15-intel
- os: macos-arm64
runner: macos-latest
- os: linux
runner: ubuntu-latest
- os: macos
runner: macos-15-intel
- os: macos-arm64
runner: macos-latest
exclude:
- os: macos-arm64
lua: luajit=@v2.0
- os: macos-arm64
lua: luajit=@v2.0
name: ${{ matrix.os }} (${{ matrix.lua }})
runs-on: ${{ matrix.runner }}
steps:
# Checks-out the repository under $GITHUB_WORKSPACE.
- uses: actions/checkout@v6
- name: Install libreadline
- name: Install libreadline
if: runner.os == 'Linux'
run: |
sudo apt-get install -y libreadline-dev
Expand All @@ -43,17 +43,22 @@ jobs:
echo lua_install/bin >> $GITHUB_PATH
env:
MACOSX_DEPLOYMENT_TARGET: 11.0

- name: Build tested
run: |
luarocks make
luarocks install luacov-coveralls

- name: Run tests

- name: Run tests (sequentially)
continue-on-error: true
run: |
tested -c -n 0

- name: Run tests (parallel)
continue-on-error: true
run: |
tested -c

- name: Save Cache
uses: actions/cache/save@v5
with:
Expand All @@ -73,7 +78,7 @@ jobs:
fail-fast: false
matrix:
lua: [lua=5.1, lua=5.2, lua=5.3, lua=5.4, luajit=@v2.0, luajit=@v2.1]
target: [mingw,vs]
target: [mingw, vs]
runs-on: windows-2022
steps:
# Checks-out the repository under $GITHUB_WORKSPACE.
Expand All @@ -90,13 +95,20 @@ jobs:
run: |
pip install git+https://github.com/luarocks/hererocks
hererocks lua_install -r^ --${{ matrix.lua }} --target ${{ matrix.target }}

- name: Build tested
run: |
.\lua_install\bin\activate
luarocks make
luarocks install luacov-coveralls
- name: Run tests

- name: Run tests (sequentially)
continue-on-error: true
run: |
.\lua_install\bin\activate
tested -c -n 0

- name: Run tests (parallel)
continue-on-error: true
run: |
.\lua_install\bin\activate
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ You can see more tests in this repo's [tests](https://github.com/FourierTransfor
- AI was used to help research Lua internals (mostly around file loading and the debug module)
- AI helped generate a prettier terminal output.
- I fed it my [original terminal output](./docs/original-output.txt), and it re-formatted it to something that looks a lot closer to the final terminal output.
- AI has been used to help debug issues

## Licenses
Parts of the following are included in the source code present in this repo:
Expand Down
25 changes: 25 additions & 0 deletions build/tested/libs/ThreadPool.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,31 @@ local _unpack = unpack or table.unpack
local function worker(num, run_coverage, linda)
logger:info("Starting worker %d", num)






local tl_ok, tl = pcall(require, "tl")
if tl_ok then
local function tl_fallback_loader(modname)

local found, fd = tl.search_module(modname, false)
if not found then return end

local code = fd:read("*all")
fd:close()
local fn, err = tl.load(code, "@" .. found)
if fn then return fn end
return nil, "Error compiling '" .. found .. "': " .. tostring(err)
end
if package.searchers then
table.insert(package.searchers, tl_fallback_loader)
else
table.insert(package.loaders, tl_fallback_loader)
end
end

local luacov

if run_coverage then
Expand Down
3 changes: 3 additions & 0 deletions build/tested/test_runner.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ function test_runner.run_tests(



local tl_ok, tl = pcall(require, "tl")
if tl_ok then tl.loader() end

local luacov_loaded, luacov_runner = pcall(require, "luacov.runner")
if options and options.coverage and not luacov_loaded then
error("Code coverage requires the luacov module to be installed")
Expand Down
4 changes: 3 additions & 1 deletion docs/teal-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ Assuming I had multiple unit test files that all pull in `utf8validator`, every

For example, if you are doing TDD, you may want to accept the performance loss and use Teal unit test files so that `tested` is _always_ using the Teal files as a source. If you have a large test suite where Lua benchmarking matters, it may make more sense to compile and then test.

In the future, I may consider adding in some way to avoid that additional compilation, so any Teal modules only get compiled once, but it sort've goes against the ethos of unit testing should be isolated if `require`'d modules start being shared across files.
Another thing to keep in mind, if there is a Lua and Teal file in the Lua's instance search path with the same `require`-able name, the Lua file will be pulled in first.

In the future, I may consider adding in some way to avoid that additional compilation, so any Teal modules only get compiled once, but it sort've goes against the ethos of unit testing (ie: tests should be isolated from one another) if `require`'d modules start being shared across files.
4 changes: 2 additions & 2 deletions src/tested/file_loader.tl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ end

function file_loader.load_and_register_handler(filepath: string)
local handler = file_loader.load_file(filepath) as types.FileLoaderHandler
file_loader.register_handler(handler.extension, handler.loader)
file_loader.register_handler(handler.extension, handler.loader)
end

local tl_ok, tl = pcall(require, "tl")
Expand All @@ -53,4 +53,4 @@ if tl_ok then
file_loader.loader[".tl"] = load_teal_file
end

return file_loader
return file_loader
45 changes: 35 additions & 10 deletions src/tested/libs/ThreadPool.tl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,32 @@ end
-- waits for a task, then executes it
local function worker(num: integer, run_coverage: boolean, linda: lanes.Linda)
logger:info("Starting worker %d", num)


-- Unfortunately have to handle this as more of a special case than I was hoping for...
-- To be able to have teal files depend on other teal files, a package loader needs to be added
-- I can't just use tl.load() to handle this here, because it causes the concurrent tests to hang
-- (similar to the luacov problems below). Still not entirely sure why, but appending this loader
-- does appear to solve the issue
local tl_ok, tl = pcall(require, "tl")
if tl_ok then
local function tl_fallback_loader(modname: string): function, string
-- search_all=false: finds only .tl files (not .lua), and respects TL_PATH
local found, fd = tl.search_module(modname, false)
if not found then return end

local code = fd:read("*all")
fd:close()
local fn, err = tl.load(code, "@" .. found)
if fn then return fn end
return nil, "Error compiling '" .. found .. "': " .. tostring(err)
end
if package.searchers then
table.insert(package.searchers, tl_fallback_loader)
else
table.insert(package.loaders, tl_fallback_loader)
end
end

local luacov: luacov_type

if run_coverage then
Expand All @@ -50,7 +75,7 @@ local function worker(num: integer, run_coverage: boolean, linda: lanes.Linda)
luacov_runner.pause()
luacov = luacov_runner
end

while true do
logger:debug("Worker %d waiting for task", num)
-- Get a task from the queue should be a blocking call
Expand All @@ -63,9 +88,9 @@ local function worker(num: integer, run_coverage: boolean, linda: lanes.Linda)
if run_coverage then luacov.pause() end

local coverage_data = {}
if run_coverage then
coverage_data = luacov.data
luacov.data = {}
if run_coverage then
coverage_data = luacov.data
luacov.data = {}
end

if success then
Expand Down Expand Up @@ -93,17 +118,17 @@ function ThreadPool.init(workers: integer, run_coverage: boolean): ThreadPool
end

function ThreadPool:map<T>(
func: function(...: any): T,
args_list: {{any}},
display_func: function(T),
func: function(...: any): T,
args_list: {{any}},
display_func: function(T),
_timeout?: number
): {ThreadPool.Result<T>}

local total_calls = #args_list
logger:info("Sending %d tasks", total_calls)
for i = 1, total_calls do
local task_data = {
order = i,
order = i,
func = func,
args = args_list[i]
}
Expand All @@ -126,7 +151,7 @@ function ThreadPool:map<T>(
return output
end
end

end

function ThreadPool:shutdown(timeout?: number)
Expand Down
13 changes: 8 additions & 5 deletions src/tested/test_runner.tl
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ function test_runner.run_with_cleanup(file_loader: types.FileLoader, test_file:
assert(type(test_module) == "table" and type(test_module.tests) == "table" and type(test_module.run_only_tests) == "boolean", "It does not appear that '" .. test_file .."' returns the 'tested' module")

local test_results = test_module:run(test_file, options)

logger:info("%s: Clearing out any packages that were loaded", test_file)
for package_name, _ in pairs(package.loaded) do
for package_name, _ in pairs(package.loaded) do
if not pre_test_loaded_packages[package_name] then
logger:debug("%s: Clearing out package: %s", test_file, package_name)
package.loaded[package_name] = nil
Expand All @@ -37,6 +37,9 @@ function test_runner.run_tests(

-- these get called in here to avoid weirdness with lanes
-- if they are called outside, the lanes will sometimes hang.
local tl_ok, tl = pcall(require, "tl")
if tl_ok then tl.loader() end

local luacov_loaded, luacov_runner = pcall(require, "luacov.runner")
if options and options.coverage and not luacov_loaded then
error("Code coverage requires the luacov module to be installed")
Expand Down Expand Up @@ -71,7 +74,7 @@ function test_runner.run_tests(

if options.coverage then luacov_runner.resume() end
local test_output = test_runner.run_with_cleanup(file_loader, test_files[i], options)
if options.coverage then
if options.coverage then
coverage = luacov_runner.data
luacov_runner.resume()
end
Expand Down Expand Up @@ -129,11 +132,11 @@ local function run_parallel_tests(
end
pool:shutdown()

-- future note: should probably save off the individual coverage results
-- future note: should probably save off the individual coverage results
-- before running the combine stats, or do a deep copy or something.
-- since the old stats get destroyed during the merge
if options.coverage then

-- mostly code from luacov to help merge stats together.
local luacov = require("luacov.runner")
luacov.data = {}
Expand Down
13 changes: 13 additions & 0 deletions tests/import_test.tl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
local tested = require("tested")
local str = require("tests.tl_to_import")

tested.test("imported files should work", function()
tested.assert({
given = "a nested string",
should = "be equivalent to imported string",
expected = "somewhat nested",
actual = str
})
end)

return tested
1 change: 1 addition & 0 deletions tests/nested_import.tl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
return "somewhat nested"
2 changes: 2 additions & 0 deletions tests/tl_to_import.tl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
local deeply_nested = require("tests.nested_import")
return deeply_nested
Loading