514 lines
15 KiB
Julia
514 lines
15 KiB
Julia
# This file is a part of Julia. License is MIT: https://julialang.org/license
|
|
|
|
# Test @test
|
|
@test true
|
|
@test 1 == 1
|
|
@test 1 != 2
|
|
@test strip("\t hi \n") == "hi"
|
|
@test strip("\t this should fail \n") != "hi"
|
|
|
|
# @test should only evaluate the arguments once
|
|
let g = Int[], f = (x) -> (push!(g, x); x)
|
|
@test f(1) == 1
|
|
@test g == [1]
|
|
end
|
|
|
|
# Test @test_broken with fail
|
|
@test_broken false
|
|
@test_broken 1 == 2
|
|
@test_broken 1 != 1
|
|
@test_broken strip("\t hi \n") != "hi"
|
|
@test_broken strip("\t this should fail \n") == "hi"
|
|
# Test @test_broken with errors
|
|
@test_broken error()
|
|
@test_broken absolute_nonsense
|
|
|
|
#Test @test_skip
|
|
@test_skip error()
|
|
@test_skip true
|
|
@test_skip false
|
|
@test_skip gobbeldygook
|
|
|
|
# Test @test_warn
|
|
@test 1234 === @test_nowarn(1234)
|
|
@test 5678 === @test_warn("WARNING: foo", begin warn("foo"); 5678; end)
|
|
let a
|
|
# Broken
|
|
# @test_throws UndefVarError a
|
|
# Replace with the previous line when #20016 is fixed
|
|
@test_throws UndefRefError a
|
|
@test_nowarn a = 1
|
|
@test a === 1
|
|
end
|
|
|
|
a = Array{Float64,5}(2, 2, 2, 2, 2)
|
|
a[1,1,1,1,1] = 10
|
|
@test a[1,1,1,1,1] == 10
|
|
@test a[1,1,1,1,1] != 2
|
|
|
|
@test rand() != rand()
|
|
|
|
# Pass - exception
|
|
@test contains(sprint(show, @test_throws ErrorException error()),
|
|
"Thrown: ErrorException")
|
|
|
|
# Test printing of Fail results
|
|
mutable struct NoThrowTestSet <: Base.Test.AbstractTestSet
|
|
results::Vector
|
|
NoThrowTestSet(desc) = new([])
|
|
end
|
|
Base.Test.record(ts::NoThrowTestSet, t::Base.Test.Result) = (push!(ts.results, t); t)
|
|
Base.Test.finish(ts::NoThrowTestSet) = ts.results
|
|
fails = @testset NoThrowTestSet begin
|
|
# Fail - wrong exception
|
|
@test_throws OverflowError error()
|
|
# Fail - no exception
|
|
@test_throws OverflowError 1 + 1
|
|
# Fail - comparison
|
|
@test 1+1 == 2+2
|
|
# Fail - approximate comparison
|
|
@test 1/1 ≈ 2/1
|
|
# Fail - chained comparison
|
|
@test 1+0 == 2+0 == 3+0
|
|
# Fail - comparison call
|
|
@test ==(1 - 2, 2 - 1)
|
|
# Error - unexpected pass
|
|
@test_broken true
|
|
end
|
|
for i in 1:length(fails) - 1
|
|
@test isa(fails[i], Base.Test.Fail)
|
|
end
|
|
|
|
str = sprint(show, fails[1])
|
|
@test contains(str, "Expression: error()")
|
|
@test contains(str, "Thrown: ErrorException")
|
|
|
|
str = sprint(show, fails[2])
|
|
@test contains(str, "Expression: 1 + 1")
|
|
@test contains(str, "No exception thrown")
|
|
|
|
str = sprint(show, fails[3])
|
|
@test contains(str, "Expression: 1 + 1 == 2 + 2")
|
|
@test contains(str, "Evaluated: 2 == 4")
|
|
|
|
str = sprint(show, fails[4])
|
|
@test contains(str, "Expression: 1 / 1 ≈ 2 / 1")
|
|
@test contains(str, "Evaluated: 1.0 ≈ 2.0")
|
|
|
|
str = sprint(show, fails[5])
|
|
@test contains(str, "Expression: 1 + 0 == 2 + 0 == 3 + 0")
|
|
@test contains(str, "Evaluated: 1 == 2 == 3")
|
|
|
|
str = sprint(show, fails[6])
|
|
@test contains(str, "Expression: 1 - 2 == 2 - 1")
|
|
@test contains(str, "Evaluated: -1 == 1")
|
|
|
|
str = sprint(show, fails[7])
|
|
@test contains(str, "Unexpected Pass")
|
|
@test contains(str, "Expression: true")
|
|
|
|
# Test printing of a TestSetException
|
|
tse_str = sprint(show, Test.TestSetException(1,2,3,4,Vector{Union{Base.Test.Error, Base.Test.Fail}}()))
|
|
@test contains(tse_str, "1 passed")
|
|
@test contains(tse_str, "2 failed")
|
|
@test contains(tse_str, "3 errored")
|
|
@test contains(tse_str, "4 broken")
|
|
|
|
@test Test.finish(Test.FallbackTestSet()) !== nothing
|
|
|
|
OLD_STDOUT = STDOUT
|
|
OLD_STDERR = STDERR
|
|
catch_out = IOStream("")
|
|
catch_err = IOStream("")
|
|
rde, wre = redirect_stderr()
|
|
rdo, wro = redirect_stdout()
|
|
|
|
# test that FallbackTestSet will throw immediately
|
|
cmd = `$(Base.julia_cmd()) --startup-file=no --depwarn=error test_exec.jl`
|
|
@test !success(pipeline(cmd))
|
|
|
|
@testset "no errors" begin
|
|
@test true
|
|
@test 1 == 1
|
|
end
|
|
|
|
# Test entirely empty test set
|
|
@testset "outer" begin
|
|
@testset "inner" begin
|
|
end
|
|
end
|
|
|
|
@testset "testset types" begin
|
|
ts = @testset "@testset should return the testset" begin
|
|
@test true
|
|
end
|
|
@test typeof(ts) == Base.Test.DefaultTestSet
|
|
@test ts.n_passed == 1
|
|
tss = @testset "@testset/for should return an array of testsets: $i" for i in 1:3
|
|
@test true
|
|
end
|
|
@test length(tss) == 3
|
|
@test typeof(tss[1]) == Base.Test.DefaultTestSet
|
|
@test tss[1].n_passed == 1
|
|
end
|
|
@testset "accounting" begin
|
|
local ts
|
|
try
|
|
ts = @testset "outer" begin
|
|
@testset "inner1" begin
|
|
@test true
|
|
@test false
|
|
@test 1 == 1
|
|
@test 2 == :foo
|
|
@test 3 == 3
|
|
@testset "d" begin
|
|
@test 4 == 4
|
|
end
|
|
@testset begin
|
|
@test :blank != :notblank
|
|
end
|
|
end
|
|
@testset "inner1" begin
|
|
@test 1 == 1
|
|
@test 2 == 2
|
|
@test 3 == :bar
|
|
@test 4 == 4
|
|
@test_throws ErrorException 1+1
|
|
@test_throws ErrorException error()
|
|
@test_throws RemoteException error()
|
|
@testset "errrrr" begin
|
|
@test "not bool"
|
|
@test error()
|
|
end
|
|
|
|
error("exceptions in testsets should be caught")
|
|
@test 1 == 1 # this test will not be run
|
|
end
|
|
|
|
@testset "loop with desc" begin
|
|
@testset "loop1 $T" for T in (Float32, Float64)
|
|
@test 1 == T(1)
|
|
end
|
|
end
|
|
@testset "loops without desc" begin
|
|
@testset for T in (Float32, Float64)
|
|
@test 1 == T(1)
|
|
end
|
|
@testset for T in (Float32, Float64), S in (Int32,Int64)
|
|
@test S(1) == T(1)
|
|
end
|
|
end
|
|
srand(123)
|
|
@testset "some loops fail" begin
|
|
@testset for i in 1:5
|
|
@test i <= rand(1:10)
|
|
end
|
|
# should add 3 errors and 3 passing tests
|
|
@testset for i in 1:6
|
|
iseven(i) || error("error outside of test")
|
|
@test true # only gets run if the above passed
|
|
end
|
|
end
|
|
end
|
|
# These lines shouldn't be called
|
|
error("No exception was thrown!")
|
|
catch ex
|
|
redirect_stdout(OLD_STDOUT)
|
|
redirect_stderr(OLD_STDERR)
|
|
ex
|
|
end
|
|
@testset "ts results" begin
|
|
@test isa(ts, Test.DefaultTestSet)
|
|
passes, fails, errors, broken, c_passes, c_fails, c_errors, c_broken = Base.Test.get_test_counts(ts)
|
|
total_pass = passes + c_passes
|
|
total_fail = fails + c_fails
|
|
total_error = errors + c_errors
|
|
total_broken = broken + c_broken
|
|
@test total_pass == 24
|
|
@test total_fail == 6
|
|
@test total_error == 6
|
|
@test total_broken == 0
|
|
end
|
|
ts.anynonpass = false
|
|
deleteat!(Base.Test.get_testset().results,1)
|
|
end
|
|
|
|
@test .1+.1+.1 ≈ .3
|
|
@test .1+.1+.1 ≉ .4
|
|
|
|
ts = @testset "@testset should return the testset" begin
|
|
@test true
|
|
end
|
|
@test typeof(ts) == Base.Test.DefaultTestSet
|
|
@test ts.n_passed == 1
|
|
|
|
tss = @testset "@testset/for should return an array of testsets: $i" for i in 1:3
|
|
@test true
|
|
end
|
|
@test length(tss) == 3
|
|
@test typeof(tss[1]) == Base.Test.DefaultTestSet
|
|
@test tss[1].n_passed == 1
|
|
|
|
# Issue #17908 (return)
|
|
testset_depth17908 = Test.get_testset_depth()
|
|
@testset for i in 1:3
|
|
i > 1 && return
|
|
@test i == 1
|
|
end
|
|
# The return aborts the control flow so the expression above doesn't return a
|
|
# value. The only thing we can test is whether the testset is properly popped.
|
|
# Do not use `@test` since the issue this is testing will swallow the error.
|
|
@assert testset_depth17908 == Test.get_testset_depth()
|
|
|
|
# Issue #17462 and Issue #17908 (break, continue)
|
|
testset_depth17462 = Test.get_testset_depth()
|
|
counter_17462_pre = 0
|
|
counter_17462_post = 0
|
|
tss17462 = @testset for x in [1,2,3,4]
|
|
counter_17462_pre += 1
|
|
if x == 1
|
|
@test counter_17462_pre == x
|
|
continue
|
|
@test false
|
|
elseif x == 3
|
|
@test counter_17462_pre == x
|
|
break
|
|
@test false
|
|
elseif x == 4
|
|
@test false
|
|
else
|
|
@test counter_17462_pre == x
|
|
@test x == 2
|
|
@test counter_17462_post == 0
|
|
end
|
|
counter_17462_post += 1
|
|
end
|
|
# Do not use `@test` since the issue this is testing will swallow the error.
|
|
# Same for the `@assert` in the for loop below
|
|
@assert testset_depth17462 == Test.get_testset_depth()
|
|
@assert length(tss17462) == 3
|
|
for ts17462 in tss17462
|
|
@assert isa(ts17462, Base.Test.DefaultTestSet)
|
|
end
|
|
@test counter_17462_pre == 3
|
|
@test counter_17462_post == 1
|
|
|
|
# Issue #21008
|
|
ts = try
|
|
@testset "@test_broken and @test_skip should not give an exception" begin
|
|
@test_broken false
|
|
@test_skip true
|
|
@test_skip false
|
|
end
|
|
catch
|
|
nothing # Shouldn't get here
|
|
end
|
|
@test ts isa Base.Test.DefaultTestSet
|
|
|
|
# now we're done running tests with DefaultTestSet so we can go back to STDOUT
|
|
redirect_stdout(OLD_STDOUT)
|
|
redirect_stderr(OLD_STDERR)
|
|
|
|
# import the methods needed for defining our own testset type
|
|
import Base.Test: record, finish
|
|
using Base.Test: get_testset_depth, get_testset
|
|
using Base.Test: AbstractTestSet, Result, Pass, Fail, Error
|
|
struct CustomTestSet <: Base.Test.AbstractTestSet
|
|
description::AbstractString
|
|
foo::Int
|
|
results::Vector
|
|
# constructor takes a description string and options keyword arguments
|
|
CustomTestSet(desc; foo=1) = new(desc, foo, [])
|
|
end
|
|
|
|
record(ts::CustomTestSet, child::AbstractTestSet) = push!(ts.results, child)
|
|
record(ts::CustomTestSet, res::Result) = push!(ts.results, res)
|
|
function finish(ts::CustomTestSet)
|
|
# just record if we're not the top-level parent
|
|
if get_testset_depth() > 0
|
|
record(get_testset(), ts)
|
|
end
|
|
ts
|
|
end
|
|
|
|
ts = @testset CustomTestSet "Testing custom testsets" begin
|
|
# this testset should inherit the parent testset type
|
|
@testset "custom testset inner 1" begin
|
|
@test true
|
|
@test false
|
|
@test error("this error will be reported as an error")
|
|
@test_throws ErrorException nothing
|
|
@test_throws ErrorException error("this error is a success")
|
|
end
|
|
# this testset has its own testset type
|
|
@testset CustomTestSet foo=4 "custom testset inner 2" begin
|
|
# this testset should inherit the type, but not the argument. If a particular
|
|
# testset type wants inheritance behavior they should implement it themselves
|
|
# using get_testset() in the constructor
|
|
@testset "custom testset inner 2 inner 1" begin
|
|
@test true
|
|
end
|
|
# make sure the RHS can use computed values, also tests options without
|
|
# specifying the testset type
|
|
@testset foo=(1+2) "custom testset inner 2 inner 2" begin
|
|
@test true
|
|
end
|
|
end
|
|
end
|
|
|
|
@test typeof(ts) == CustomTestSet
|
|
@test ts.foo == 1
|
|
@test ts.description == "Testing custom testsets"
|
|
@test typeof(ts.results[1]) == CustomTestSet
|
|
@test ts.results[1].description == "custom testset inner 1"
|
|
@test ts.results[1].foo == 1
|
|
@test typeof(ts.results[1].results[1]) == Pass
|
|
@test typeof(ts.results[1].results[2]) == Fail
|
|
@test typeof(ts.results[1].results[3]) == Error
|
|
@test typeof(ts.results[1].results[4]) == Fail
|
|
@test typeof(ts.results[1].results[5]) == Pass
|
|
|
|
@test typeof(ts.results[2]) == CustomTestSet
|
|
@test ts.results[2].description == "custom testset inner 2"
|
|
@test ts.results[2].foo == 4
|
|
@test typeof(ts.results[2].results[1]) == CustomTestSet
|
|
@test ts.results[2].results[1].foo == 1
|
|
@test typeof(ts.results[2].results[1].results[1]) == Pass
|
|
@test typeof(ts.results[2].results[2]) == CustomTestSet
|
|
@test ts.results[2].results[2].foo == 3
|
|
|
|
# test custom testset types on testset/for
|
|
tss = @testset CustomTestSet foo=3 "custom testset $i" for i in 1:6
|
|
@testset "inner testset $i-$j" for j in 1:3
|
|
@test iseven(i + j)
|
|
end
|
|
# make sure a testset within a testset/for works
|
|
@testset "inner testset $i" begin
|
|
@test iseven(i)
|
|
end
|
|
end
|
|
|
|
|
|
for i in 1:6
|
|
@test typeof(tss[i]) == CustomTestSet
|
|
@test tss[i].foo == 3
|
|
for j in 1:3
|
|
@test typeof(tss[i].results[j]) == CustomTestSet
|
|
@test tss[i].results[j].foo == 1
|
|
@test typeof(tss[i].results[j].results[1]) == (iseven(i+j) ? Pass : Fail)
|
|
end
|
|
@test typeof(tss[i].results[4]) == CustomTestSet
|
|
@test typeof(tss[i].results[4].results[1]) == (iseven(i) ? Pass : Fail)
|
|
end
|
|
|
|
# test @inferred
|
|
function uninferrable_function(i)
|
|
q = [1, "1"]
|
|
return q[i]
|
|
end
|
|
|
|
@test_throws ErrorException @inferred(uninferrable_function(1))
|
|
@test @inferred(identity(1)) == 1
|
|
|
|
# Ensure @inferred only evaluates the arguments once
|
|
inferred_test_global = 0
|
|
function inferred_test_function()
|
|
global inferred_test_global
|
|
inferred_test_global += 1
|
|
true
|
|
end
|
|
@test @inferred inferred_test_function()
|
|
@test inferred_test_global == 1
|
|
|
|
# Test that @inferred works with A[i] expressions
|
|
@test @inferred((1:3)[2]) == 2
|
|
struct SillyArray <: AbstractArray{Float64,1} end
|
|
Base.getindex(a::SillyArray, i) = rand() > 0.5 ? 0 : false
|
|
test_result = @test_throws ErrorException @inferred(SillyArray()[2])
|
|
@test contains(test_result.value.msg, "Bool")
|
|
|
|
# Issue #14928
|
|
# Make sure abstract error type works.
|
|
@test_throws Exception error("")
|
|
|
|
# Issue #17105
|
|
# @inferred with kwargs
|
|
function inferrable_kwtest(x; y=1)
|
|
2x
|
|
end
|
|
function uninferrable_kwtest(x; y=1)
|
|
2x+y
|
|
end
|
|
@test @inferred(inferrable_kwtest(1)) == 2
|
|
@test @inferred(inferrable_kwtest(1; y=1)) == 2
|
|
@test @inferred(uninferrable_kwtest(1)) == 3
|
|
@test_throws ErrorException @inferred(uninferrable_kwtest(1; y=2)) == 2
|
|
|
|
@test_throws ErrorException @testset "$(error())" for i in 1:10
|
|
end
|
|
@test_throws ErrorException @testset "$(error())" begin
|
|
end
|
|
|
|
io = IOBuffer()
|
|
@test (print(io, Base.Test.Error(:test_error, "woot", 5, backtrace())); 1) == 1
|
|
str = String(take!(io))
|
|
# NOTE: This test depends on the code generated by @testset getting compiled,
|
|
# to get good backtraces. If it fails, check the implementation of `testset_beginend`.
|
|
@test contains(str, "test.jl")
|
|
@test !contains(str, "boot.jl")
|
|
|
|
let io = IOBuffer()
|
|
exc = Test.TestSetException(1,2,3,4,Vector{Union{Base.Test.Error, Base.Test.Fail}}())
|
|
Base.showerror(io, exc, backtrace())
|
|
@test !contains(String(take!(io)), "backtrace()")
|
|
end
|
|
|
|
# 19750
|
|
let io = IOBuffer()
|
|
exc = Test.TestSetException(1,2,3,4,Vector{Union{Base.Test.Error, Base.Test.Fail}}())
|
|
Base.showerror(io, exc, backtrace())
|
|
@test !contains(String(take!(io)), "backtrace()")
|
|
|
|
exc = Test.FallbackTestSetException("msg")
|
|
Base.showerror(io, exc, backtrace())
|
|
str = String(take!(io))
|
|
@test contains(str, "msg")
|
|
@test !contains(str, "backtrace()")
|
|
end
|
|
|
|
msg = readstring(pipeline(ignorestatus(`$(Base.julia_cmd()) --startup-file=no --color=no -e '
|
|
using Base.Test
|
|
|
|
foo(x) = length(x)^2
|
|
|
|
@testset "Foo Tests" begin
|
|
@testset "Animals" begin
|
|
@testset "Felines" begin
|
|
@test foo("cat") == 9
|
|
end
|
|
@testset "Canines" begin
|
|
@test foo("dog") == 11
|
|
end
|
|
end
|
|
@testset "Arrays" begin
|
|
@test foo(zeros(2)) == 4
|
|
@test foo(ones(4)) == 15
|
|
end
|
|
end'`), stderr=DevNull))
|
|
|
|
@test contains(msg,
|
|
"""
|
|
Test Summary: | Pass Fail Total
|
|
Foo Tests | 2 2 4
|
|
Animals | 1 1 2
|
|
Felines | 1 1
|
|
Canines | 1 1
|
|
Arrays | 1 1 2
|
|
""")
|
|
|
|
# 20489
|
|
msg = split(readstring(pipeline(ignorestatus(`$(Base.julia_cmd()) --startup-file=no --color=no -e '
|
|
Test.print_test_results(Test.DefaultTestSet(""))'`), stderr=DevNull)), "\n")[1]
|
|
|
|
@test msg == rstrip(msg)
|