Skip to content

Commit

Permalink
Refactor Runic.main tests to also cover juliac code paths (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikekre authored Nov 19, 2024
1 parent 829dc34 commit c72cfb4
Show file tree
Hide file tree
Showing 3 changed files with 414 additions and 344 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/Test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ jobs:
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
with:
directories: "src,juliac"
- uses: codecov/codecov-action@v4
with:
file: lcov.info
Expand Down
366 changes: 366 additions & 0 deletions test/maintests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,366 @@
# SPDX-License-Identifier: MIT

using Test: @test
using Runic: Runic

function maintests(f::R) where {R}

bad = "1+1"
good = "1 + 1\n"

# Utils
function cdtmp(f)
return mktempdir(tmp -> cd(f, tmp))
end
function runic(std_in::String)
return runic(String[], std_in)
end
function runic(argv::Vector{String} = String[], std_in::String = "")
rc, stdout_str, stderr_str = mktemp() do stdin_path, stdin
write(stdin_path, std_in)
mktemp() do stdout_path, stdout
mktemp() do stderr_path, stderr
rc = redirect_stdio(() -> f(copy(argv)); stdin, stdout, stderr)
close(stderr)
close(stdout)
return rc, read(stdout_path, String), read(stderr_path, String)
end
end
end
return rc, stdout_str, stderr_str
end

# runic --help
let (rc, fd1, fd2) = runic(["--help"])
@test rc == 0
@test occursin("Runic.main - format Julia source code", fd1)
@test isempty(fd2)
end

# runic --version
let (rc, fd1, fd2) = runic(["--version"])
@test rc == 0
@test occursin("runic version $(Runic.RUNIC_VERSION), julia version $(VERSION)", fd1)
@test isempty(fd2)
end

# runic <stdin >stdout
for argv in [
String[], ["-"],
["--output=-"], ["-o", "-"],
["--output=-", "-"], ["-o", "-", "-"],
]
rc, fd1, fd2 = runic(argv, bad)
@test rc == 0
@test occursin(good, fd1)
@test isempty(fd2)
end

# runic --output=out.jl <stdin
cdtmp() do
f_out = "out.jl"
for argv in [
["--output=$f_out"], ["-o", f_out],
["--output=$f_out", "-"], ["-o", f_out, "-"],
]
rm(f_out, force = true)
rc, fd1, fd2 = runic(argv, bad)
@test rc == 0
@test isempty(fd1)
@test isempty(fd2)
@test read(f_out, String) == good
end
end

# runic in.jl >stdout
cdtmp() do
f_in = "in.jl"
write(f_in, bad)
for argv in [[f_in], ["--output=-", f_in], ["-o", "-", f_in]]
rc, fd1, fd2 = runic(argv)
@test rc == 0
@test occursin(good, fd1)
@test isempty(fd2)
@test read(f_in, String) == bad
end
end

# runic --output=out.jl in.jl
cdtmp() do
f_in = "in.jl"
write(f_in, bad)
f_out = "out.jl"
for argv in [["--output=$f_out", f_in], ["-o", f_out, f_in]]
rm(f_out, force = true)
rc, fd1, fd2 = runic(argv)
@test rc == 0
@test isempty(fd1)
@test occursin("Formatting `in.jl` -> `out.jl` ...", fd2)
@test occursin("", fd2)
@test !occursin("", fd2)
@test read(f_out, String) == good
@test read(f_in, String) == bad
end
end

# runic --inplace in.jl (bad input)
cdtmp() do
f_in = "in.jl"
for argv in [["--inplace", f_in], ["-i", f_in]]
write(f_in, bad)
rc, fd1, fd2 = runic(argv)
@test rc == 0
@test isempty(fd1)
@test occursin("Formatting `in.jl` ...", fd2)
@test occursin("", fd2)
@test !occursin("", fd2)
@test read(f_in, String) == good
end
end

# runic --inplace in.jl (good input)
cdtmp() do
f_in = "in.jl"
for argv in [["--inplace", f_in], ["-i", f_in]]
write(f_in, good)
rc, fd1, fd2 = runic(argv)
@test rc == 0
@test isempty(fd1)
@test occursin("Formatting `in.jl` ...", fd2)
@test occursin("", fd2)
@test !occursin("", fd2)
@test read(f_in, String) == good
end
end

# runic --inplace in/
cdtmp() do
fgood = "good.jl"
mkdir("src")
fbad = joinpath("src", "bad.jl")
mkdir(".git")
gitfile = joinpath(".git", "git.jl")
write(gitfile, "this is not a Julia file")
markdownfile = "markdown.md"
write(markdownfile, "this is not a Julia file")
for argv in [["--inplace", "."], ["-i", "."], ["-i", ".", "src"]]
write(fgood, good)
write(fbad, bad)
rc, fd1, fd2 = runic(argv)
@test rc == 0
@test isempty(fd1)
@test occursin("Formatting `good.jl` ...", fd2)
@test occursin("Formatting `src/bad.jl` ...", fd2)
@test occursin("", fd2)
@test !occursin("", fd2)
@test !occursin("git.jl", fd2)
@test !occursin("markdown.jl", fd2)
@test read(fgood, String) == read(fbad, String) == good
end
end

# runic --check in.jl (bad input)
cdtmp() do
f_in = "in.jl"
for argv in [["--check", f_in], ["-c", f_in]]
write(f_in, bad)
rc, fd1, fd2 = runic(argv)
@test rc == 1
@test isempty(fd1)
@test occursin("Checking `in.jl` ...", fd2)
@test !occursin("", fd2)
@test occursin("", fd2)
@test read(f_in, String) == bad
end
end

# runic --check in.jl (good input)
cdtmp() do
f_in = "in.jl"
for argv in [["--check", f_in], ["-c", f_in]]
write(f_in, good)
rc, fd1, fd2 = runic(argv)
@test rc == 0
@test isempty(fd1)
@test occursin("Checking `in.jl` ...", fd2)
@test occursin("", fd2)
@test !occursin("", fd2)
@test read(f_in, String) == good
end
end

# runic --check in/
cdtmp() do
fgood = "good.jl"
mkdir("src")
fbad = joinpath("src", "bad.jl")
mkdir(".git")
gitfile = joinpath(".git", "git.jl")
write(gitfile, "this is not a Julia file")
markdownfile = "markdown.md"
write(markdownfile, "this is not a Julia file")
for argv in [["--check", "."], ["-c", "."]]
write(fgood, good)
write(fbad, bad)
rc, fd1, fd2 = runic(argv)
@test rc == 1
@test isempty(fd1)
@test occursin("Checking `good.jl` ...", fd2)
@test occursin("Checking `src/bad.jl` ...", fd2)
@test occursin("", fd2)
@test occursin("", fd2)
@test !occursin("git.jl", fd2)
@test !occursin("markdown.jl", fd2)
@test read(fgood, String) == good
@test read(fbad, String) == bad
end
end

# runic --check --diff in.jl
if Sys.which("git") !== nothing
cdtmp() do
f_in = "in.jl"
for argv in [["--check", "--diff", f_in], ["-c", "-d", f_in]]
write(f_in, bad)
rc, fd1, fd2 = runic(argv)
@test rc == 1
@test isempty(fd1)
@test occursin("Checking `in.jl` ...", fd2)
@test !occursin("", fd2)
@test occursin("", fd2)
@test occursin("diff --git", fd2)
@test occursin("-1+1", fd2)
@test occursin("+1 + 1", fd2)
@test read(f_in, String) == bad
end
end
end

# Error paths
# runic -o
let (rc, fd1, fd2) = runic(["-o"])
@test rc == 1
@test isempty(fd1)
@test occursin("expected output file argument after `-o`", fd2)
end

# runic in.jl -
let (rc, fd1, fd2) = runic(["in.jl", "-"])
@test rc == 1
@test isempty(fd1)
@test occursin("input `-` can not be used with multiple files", fd2)
end

# runic --inplace --check (TODO: perhaps this should be allowed?)
let (rc, fd1, fd2) = runic(["--inplace", "--check"])
@test rc == 1
@test isempty(fd1)
@test occursin("options `--inplace` and `--check` are mutually exclusive", fd2)
end

# runic --inplace --output=out.jl in.jl
let (rc, fd1, fd2) = runic(["--inplace", "--output=out.jl", "in.jl"])
@test rc == 1
@test isempty(fd1)
@test occursin("options `--inplace` and `--output` are mutually exclusive", fd2)
end

# runic --check --output=out.jl in.jl
let (rc, fd1, fd2) = runic(["--check", "--output=out.jl", "in.jl"])
@test rc == 1
@test isempty(fd1)
@test occursin("options `--check` and `--output` are mutually exclusive", fd2)
end

# runic --inplace
let (rc, fd1, fd2) = runic(["--inplace"])
@test rc == 1
@test isempty(fd1)
@test occursin("option `--inplace` can not be used together with stdin input", fd2)
end

# runic --output=out.jl in1.jl in2.jl
let (rc, fd1, fd2) = runic(["--output=out.jl", "in1.jl", "in2.jl"])
@test rc == 1
@test isempty(fd1)
@test occursin("option `--output` can not be used together with multiple input files", fd2)
end

# runic in1.jl in2.jl
let (rc, fd1, fd2) = runic(["in1.jl", "in2.jl"])
@test rc == 1
@test isempty(fd1)
@test occursin("option `--inplace` or `--check` required with multiple input files", fd2)
end

# runic --diff (with no git)
let (rc, fd1, fd2) = withenv(() -> runic(["--diff"]), "PATH" => "")
@test rc == 1
@test isempty(fd1)
@test occursin("option `--diff` requires `git` to be installed", fd2)
end

# runic in.jl (not readable)
cdtmp() do
f_in = "in.jl"
write(f_in, bad)
omode = filemode(f_in)
chmod(f_in, omode & (typemax(omode) 0o444))
rc, fd1, fd2 = runic([f_in])
chmod(f_in, omode)
@test rc == 1
@test isempty(fd1)
@test occursin("could not read input from file", fd2)
@test occursin("SystemError: opening file", fd2)
end

# runic doesntexist.jl
cdtmp() do
rc, fd1, fd2 = runic(["doesntexist.jl"])
@test rc == 1
@test isempty(fd1)
@test occursin("input file does not exist", fd2)
end

# runic -o in.jl in.jl
cdtmp() do
f_in = "in.jl"
write(f_in, bad)
rc, fd1, fd2 = runic(["-o", f_in, f_in])
@test rc == 1
@test isempty(fd1)
@test occursin("can not use same file for input and output", fd2)
end

# runic --check unparseable.jl
cdtmp() do
f_in = "in.jl"
write(f_in, "syntax error")
rc, fd1, fd2 = runic(["--check", f_in])
@test rc == 1
@test isempty(fd1)
@test occursin("failed to parse input", fd2)
end

# runic -o readonly.jl in.jl
return cdtmp() do
f_in = "in.jl"
write(f_in, bad)
f_out = "readonly.jl"
touch(f_out)
omode = filemode(f_out)
chmod(f_out, omode & (typemax(omode) 0o222))
rc, fd1, fd2 = runic(["-o", f_out, f_in])
chmod(f_out, omode)
@test rc == 1
@test isempty(fd1)
@test occursin("could not write to output file", fd2)
end
end

# rc = let argv = pushfirst!(copy(argv), "runic"), argc = length(argv) % Cint
# GC.@preserve argv begin
# argvptr = Base.unsafe_convert(Ptr{Ptr{UInt8}}, Base.cconvert(Ptr{Ptr{UInt8}}, argv))
# redirect_stdio(() -> Main.RunicC.main(argc, argvptr); stdin, stdout, stderr)
# end
# end
Loading

0 comments on commit c72cfb4

Please sign in to comment.