mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-08-06 04:21:33 +00:00
fa762a11ec
The default harness loads shared helpers and smoke checks before topic includes, registers poroelastic and thermo_poroelastic, drops the retired IO topic, and removes the orphaned ASCII fixture. - Add zero_alloc_helpers.jl, test_api_contract.jl, test_pkg_hygiene.jl, and test_inference_smoke.jl included once from runtests.jl - Extend TOPICS; remove io; clarify test_args accepts topic names only - Delete test/testdata/cantilever_beam.msh
105 lines
3.4 KiB
Julia
105 lines
3.4 KiB
Julia
# SPDX-FileCopyrightText: 2015-2026 Jukka Aho
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
"""
|
|
Cross-cutting API contract tests for LLM-heavy workflows.
|
|
|
|
1. Every `export` name listed in `src/exports.jl` resolves in `JuliaFEM`
|
|
after `using JuliaFEM` (catches dropped bindings / typos in exports).
|
|
2. Every directory listed in `TOPICS` in `test/runtests.jl` contains a
|
|
`runtests.jl` entry point (catches forgotten wiring when adding topics).
|
|
|
|
Call `run_api_contract_tests(TOPICS, test_root_dir)` from `test/runtests.jl`
|
|
inside the main `@testset` so results nest correctly (`include` alone would
|
|
evaluate child testsets at module scope).
|
|
"""
|
|
|
|
using Test
|
|
|
|
"""
|
|
Parse `src/exports.jl` export statements, including comma-continued blocks.
|
|
|
|
Each comma-separated token is validated with `Base.Meta.parse`, so Unicode
|
|
identifiers (for example `owned_norm²_packed`) and macro exports (`@DOFSet`)
|
|
are accepted. Returns a `Vector{Symbol}` of unique exported names (order
|
|
preserved).
|
|
"""
|
|
function _parse_exported_symbols(exports_path::String)
|
|
lines = readlines(exports_path)
|
|
names = Symbol[]
|
|
seen = Set{Symbol}()
|
|
i = 1
|
|
while i ≤ length(lines)
|
|
raw = lines[i]
|
|
stripped = lstrip(raw)
|
|
if !startswith(stripped, "export ")
|
|
i += 1
|
|
continue
|
|
end
|
|
rest = stripped[begin+length("export "):end]
|
|
hash = findfirst('#', rest)
|
|
if hash !== nothing
|
|
rest = rest[1:prevind(rest, hash)]
|
|
end
|
|
buf = IOBuffer()
|
|
print(buf, rest)
|
|
i += 1
|
|
while i ≤ length(lines)
|
|
cont = lines[i]
|
|
t = lstrip(cont)
|
|
isempty(t) && break
|
|
startswith(t, "export ") && break
|
|
startswith(t, '#') && break
|
|
print(buf, ' ')
|
|
h2 = findfirst('#', cont)
|
|
chunk = h2 === nothing ? cont : cont[1:prevind(cont, h2)]
|
|
print(buf, strip(chunk))
|
|
i += 1
|
|
end
|
|
blob = String(take!(buf))
|
|
for part in split(blob, ',')
|
|
tok = strip(part)
|
|
isempty(tok) && continue
|
|
ex = Base.Meta.parse(tok; raise = false)
|
|
sym = if ex isa Symbol
|
|
ex::Symbol
|
|
elseif ex isa Expr && ex.head === :macrocall && length(ex.args) ≥ 1 && ex.args[1] isa Symbol
|
|
ex.args[1]::Symbol
|
|
else
|
|
error("Unexpected export token in exports.jl: $(repr(tok))")
|
|
end
|
|
if !(sym in seen)
|
|
push!(names, sym)
|
|
push!(seen, sym)
|
|
end
|
|
end
|
|
end
|
|
return names
|
|
end
|
|
|
|
"""
|
|
Run nested `@testset`s under the caller's current testset context.
|
|
"""
|
|
function run_api_contract_tests(topics, test_root_dir::String)
|
|
@testset "TOPICS directories have runtests.jl" begin
|
|
for topic in topics
|
|
p = joinpath(test_root_dir, topic, "runtests.jl")
|
|
@test isfile(p)
|
|
end
|
|
@test length(topics) == length(unique(topics))
|
|
end
|
|
|
|
@testset "exports.jl names are defined on JuliaFEM" begin
|
|
exports_path = joinpath(test_root_dir, "..", "src", "exports.jl")
|
|
@test isfile(exports_path)
|
|
syms = _parse_exported_symbols(exports_path)
|
|
@test length(syms) ≥ 200
|
|
missing = [s for s in syms if !isdefined(JuliaFEM, s)]
|
|
if !isempty(missing)
|
|
@error "exports.jl lists symbols not defined on JuliaFEM" missing = missing
|
|
end
|
|
@test isempty(missing)
|
|
end
|
|
return nothing
|
|
end
|