From 57b1ba56a4d8fd49babcb21ef20cee3d9ced694e Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 27 Jul 2024 18:08:33 -0500 Subject: [PATCH] Test Cthulhu extension `ascend` is a terminal program so it takes a bit of effort to test it. xref https://github.com/JuliaDebug/Cthulhu.jl/issues/581 --- .github/workflows/ci.yml | 1 + Project.toml | 4 +- test/extensions/cthulhu.jl | 91 ++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 16 ++++--- 4 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 test/extensions/cthulhu.jl diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 42db9d2e..0af3edf7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,6 +49,7 @@ jobs: - run: julia --project -e 'using Pkg; Pkg.develop([PackageSpec(path="SnoopCompileCore")])' - uses: julia-actions/julia-buildpkg@latest - uses: julia-actions/julia-runtest@latest + - run: julia --check-bounds=yes --project -e 'using Pkg; Pkg.test(; test_args=["cthulhu"], coverage=true)' - uses: julia-actions/julia-processcoverage@v1 with: directories: src,SnoopCompileCore/src diff --git a/Project.toml b/Project.toml index 726c37dd..9d40d6db 100644 --- a/Project.toml +++ b/Project.toml @@ -43,6 +43,7 @@ PyPlot = "2" Random = "1" Serialization = "1" SnoopCompileCore = "3" +REPL = "1" Test = "1" YAML = "0.4" julia = "1.10" @@ -55,7 +56,8 @@ MethodAnalysis = "85b6ec6f-f7df-4429-9514-a64bcd9ee824" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Cthulhu", "PrettyTables", "Documenter", "JET", "MethodAnalysis", "Pkg", "Random", "Test"] +test = ["Cthulhu", "PrettyTables", "Documenter", "JET", "MethodAnalysis", "Pkg", "Random", "REPL", "Test"] diff --git a/test/extensions/cthulhu.jl b/test/extensions/cthulhu.jl new file mode 100644 index 00000000..354bfdd7 --- /dev/null +++ b/test/extensions/cthulhu.jl @@ -0,0 +1,91 @@ +module CthulhuExtTest + +using SnoopCompileCore, SnoopCompile +using Cthulhu +using Pkg +using Test + +if !isdefined(@__MODULE__, :fake_terminal) + @eval (@__MODULE__) begin + Base.include(@__MODULE__, normpath(pkgdir(Cthulhu), "test", "FakeTerminals.jl")) + using .FakeTerminals + end +end + +macro with_try_stderr(out, expr) + quote + try + $(esc(expr)) + catch err + bt = catch_backtrace() + Base.display_error(stderr, err, bt) + end + end +end + +# Test functions +myplus(x, y) = x + y +function f(x) + x < 0.25 ? 1 : + x < 0.5 ? 1.0 : + x < 0.75 ? 0x01 : Float16(1) +end +g(c) = myplus(f(c[1]), f(c[2])) + + +@testset "Cthulhu extension" begin + @testset "ascend for invalidations" begin + cproj = Base.active_project() + cd(joinpath(dirname(@__DIR__), "testmodules", "Invalidation")) do + Pkg.activate(pwd()) + Pkg.develop(path="./PkgC") + Pkg.develop(path="./PkgD") + Pkg.precompile() + invalidations = @snoop_invalidations begin + @eval begin + using PkgC + PkgC.nbits(::UInt8) = 8 + using PkgD + end + end + tree = only(invalidation_trees(invalidations)) + sig, root = only(tree.mt_backedges) + + fake_terminal() do term, in, out, _ + t = @async begin + @with_try_stderr out ascend(term, root; interruptexc=false) + end + lines = String(readavailable(out)) # this gets the header + lines = String(readavailable(out)) + @test occursin("call_nbits", lines) + @test occursin("map_nbits(::Vector{Integer})", lines) + # the job of the extension is done once we've written the menu, so we can quit here + write(in, 'q') + wait(t) + end + end + + Pkg.activate(cproj) + end + + @testset "ascend for inference triggers" begin + tinf = @snoop_inference g([0.7, 0.8]) + itrigs = inference_triggers(tinf; exclude_toplevel=false) + itrig = last(itrigs) + + fake_terminal() do term, in, out, _ + t = @async begin + @with_try_stderr out ascend(term, itrig; interruptexc=false) + end + lines = String(readavailable(out)) # this gets the header + lines = String(readavailable(out)) + @test occursin("myplus(::UInt8, ::Float16)", lines) + @test occursin("g(::Vector{Float64})", lines) + # the job of the extension is done once we've written the menu, so we can quit here + write(in, 'q') + wait(t) + end + end +end + +end diff --git a/test/runtests.jl b/test/runtests.jl index b365fe98..d29296c4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,10 +1,14 @@ using Test using SnoopCompile -include("snoop_inference.jl") -include("snoop_llvm.jl") -include("snoop_invalidations.jl") +if !isempty(ARGS) + "cthulhu" ∈ ARGS && include("extensions/cthulhu.jl") +else + include("snoop_inference.jl") + include("snoop_llvm.jl") + include("snoop_invalidations.jl") -# otherwise-untested demos -retflat = SnoopCompile.flatten_demo() -@test !isempty(retflat.children) + # otherwise-untested demos + retflat = SnoopCompile.flatten_demo() + @test !isempty(retflat.children) +end