# This file is a part of Julia. License is MIT: https://julialang.org/license isdefined(Main, :FakePTYs) || @eval Main include("testhelpers/FakePTYs.jl") include("testhelpers/withlocales.jl") # Tests that do not really go anywhere else # test @assert macro @test_throws AssertionError (@assert 1 == 2) @test_throws AssertionError (@assert false) @test_throws AssertionError (@assert false "this is a test") @test_throws AssertionError (@assert false "this is a test" "another test") @test_throws AssertionError (@assert false :a) let try @assert 1 == 2 error("unexpected") catch ex @test isa(ex, AssertionError) @test occursin("1 == 2", ex.msg) end end # test @assert message let try @assert 1 == 2 "this is a test" error("unexpected") catch ex @test isa(ex, AssertionError) @test ex.msg == "this is a test" end end # @assert only uses the first message string let try @assert 1 == 2 "this is a test" "this is another test" error("unexpected") catch ex @test isa(ex, AssertionError) @test ex.msg == "this is a test" end end # @assert calls string() on second argument let try @assert 1 == 2 :random_object error("unexpected") catch ex @test isa(ex, AssertionError) @test !occursin("1 == 2", ex.msg) @test occursin("random_object", ex.msg) end end # if the second argument is an expression, c let deepthought(x, y) = 42 try @assert 1 == 2 string("the answer to the ultimate question: ", deepthought(6, 9)) error("unexpected") catch ex @test isa(ex, AssertionError) @test ex.msg == "the answer to the ultimate question: 42" end end let # test the process title functions, issue #9957 oldtitle = Sys.get_process_title() Sys.set_process_title("julia0x1") @test Sys.get_process_title() == "julia0x1" Sys.set_process_title(oldtitle) @test Sys.get_process_title() == oldtitle end # test GC.enable/disable @test GC.enable(true) @test GC.enable(false) @test GC.enable(false) == false @test GC.enable(true) == false @test GC.enable(true) # PR #10984 let redir_err = "redirect_stderr(stdout)" exename = Base.julia_cmd() script = """ $redir_err module A; f() = 1; end; A.f() = 1 A.f() = 1 outer() = (g() = 1; g() = 2; g) """ warning_str = read(`$exename --warn-overwrite=yes --startup-file=no -e $script`, String) @test warning_str == """ WARNING: Method definition f() in module A at none:2 overwritten in module Main on the same line (check for duplicate calls to `include`). WARNING: Method definition f() in module Main at none:2 overwritten at none:3. WARNING: Method definition g() in module Main at none:4 overwritten on the same line. """ warning_str = read(`$exename --startup-file=no -e $script`, String) @test warning_str == """ WARNING: Method definition g() in module Main at none:4 overwritten on the same line. """ end # Debugging tool: return the current state of the enable_finalizers counter. get_finalizers_inhibited() = ccall(:jl_gc_get_finalizers_inhibited, Int32, (Ptr{Cvoid},), C_NULL) # lock / unlock let l = ReentrantLock() @test lock(l) === nothing @test islocked(l) success = Ref(false) @test trylock(l) do @test lock(l) do success[] = true return :foo end === :foo return :bar end === :bar @test success[] t = @async begin @test trylock(l) do error("unreachable") end === false end @test get_finalizers_inhibited() == 1 Base.wait(t) @test get_finalizers_inhibited() == 1 @test unlock(l) === nothing @test get_finalizers_inhibited() == 0 @test_throws ErrorException unlock(l) end for l in (Threads.SpinLock(), ReentrantLock()) @test get_finalizers_inhibited() == 0 @test lock(get_finalizers_inhibited, l) == 1 @test get_finalizers_inhibited() == 0 try GC.enable_finalizers(false) GC.enable_finalizers(false) @test get_finalizers_inhibited() == 2 GC.enable_finalizers(true) @test get_finalizers_inhibited() == 1 finally @test get_finalizers_inhibited() == 1 GC.enable_finalizers(false) @test get_finalizers_inhibited() == 2 end @test get_finalizers_inhibited() == 2 GC.enable_finalizers(true) @test get_finalizers_inhibited() == 1 GC.enable_finalizers(true) @test get_finalizers_inhibited() == 0 if Base.isdebugbuild() # Note this warning only exists in debug builds @test_warn "WARNING: GC finalizers already enabled on this thread." GC.enable_finalizers(true) end @test lock(l) === nothing @test try unlock(l) finally end === nothing end @testset "Semaphore" begin sem_size = 2 n = 100 s = Base.Semaphore(sem_size) # explicit acquire-release form clock = Threads.Atomic{Int}(1) occupied = Threads.Atomic{Int}(0) history = fill!(Vector{Int}(undef, 2n), -1) @sync for _ in 1:n @async begin Base.acquire(s) history[Threads.atomic_add!(clock, 1)] = Threads.atomic_add!(occupied, 1) + 1 sleep(rand(0:0.01:0.1)) history[Threads.atomic_add!(clock, 1)] = Threads.atomic_sub!(occupied, 1) - 1 Base.release(s) end end @test all(<=(sem_size), history) @test all(>=(0), history) @test history[end] == 0 # do-block syntax clock = Threads.Atomic{Int}(1) occupied = Threads.Atomic{Int}(0) history = fill!(Vector{Int}(undef, 2n), -1) @sync for _ in 1:n @async begin @test Base.acquire(s) do history[Threads.atomic_add!(clock, 1)] = Threads.atomic_add!(occupied, 1) + 1 sleep(rand(0:0.01:0.1)) history[Threads.atomic_add!(clock, 1)] = Threads.atomic_sub!(occupied, 1) - 1 return :resultvalue end === :resultvalue end end @test all(<=(sem_size), history) @test all(>=(0), history) @test history[end] == 0 end # task switching @noinline function f6597(c) t = @async nothing finalizer(t -> c[] += 1, t) Base.wait(t) @test c[] == 0 Base.wait(t) nothing end let c = Ref(0), t2 = @async (wait(); c[] += 99) @test c[] == 0 f6597(c) GC.gc() # this should run the finalizer for t @test c[] == 1 yield() @test c[] == 1 yield(t2) @test c[] == 100 end @test_throws ErrorException("deadlock detected: cannot wait on current task") wait(current_task()) # issue #41347 let t = @async 1 wait(t) @test_throws ErrorException yield(t) end let t = @async error(42) Base._wait(t) @test_throws ErrorException("42") yieldto(t) end # test that @sync is lexical (PR #27164) const x27164 = Ref(0) const c27164 = Base.Event() do_something_async_27164() = @async(begin wait(c27164); x27164[] = 2; end) let t = nothing @sync begin @async (sleep(0.1); x27164[] = 1) t = do_something_async_27164() end @test x27164[] == 1 notify(c27164) fetch(t) @test x27164[] == 2 end # timing macros # test that they don't introduce global vars global v11801, t11801, names_before_timing names_before_timing = names(@__MODULE__, all = true) let t = @elapsed 1+1 @test isa(t, Real) && t >= 0 end let stats = @timed sin(1) @test stats.value == sin(1) @test isa(stats.time, Real) && stats.time >= 0 # The return type of gcstats was changed in Julia 1.4 (# 34147) # Test that the 1.0 API still works val, t, bytes, gctime, gcstats = stats @test val === stats.value @test t === stats.time @test bytes === stats.bytes @test gctime === stats.gctime @test gcstats === stats.gcstats end # problem after #11801 - at global scope t11801 = @elapsed 1+1 @test isa(t11801,Real) && t11801 >= 0 v11801, t11801 = @timed sin(1) @test v11801 == sin(1) @test isa(t11801,Real) && t11801 >= 0 @test names(@__MODULE__, all = true) == names_before_timing redirect_stdout(devnull) do # suppress time prints # Accepted @time argument formats @test @time true @test @time "message" true let msg = "message" @test @time msg true end let foo() = "message" @test @time foo() true end # Accepted @timev argument formats @test @timev true @test @timev "message" true let msg = "message" @test @timev msg true end let foo() = "message" @test @timev foo() true end # @showtime @test @showtime true let foo() = true @test @showtime foo() end let foo() = false @test (@showtime foo()) == false end # PR #39133, ensure that @time evaluates in the same scope function time_macro_scope() try # try/throw/catch bypasses printing @time (time_macro_local_var = 1; throw("expected")) return time_macro_local_var catch ex ex === "expected" || rethrow() end end @test time_macro_scope() == 1 function timev_macro_scope() try # try/throw/catch bypasses printing @timev (time_macro_local_var = 1; throw("expected")) return time_macro_local_var catch ex ex === "expected" || rethrow() end end @test timev_macro_scope() == 1 before_comp, before_recomp = Base.cumulative_compile_time_ns() # no need to turn timing on, @time will do that # exercise concurrent calls to `@time` for reentrant compilation time measurement. @sync begin t1 = @async @time begin sleep(2) @eval module M ; f(x,y) = x+y ; end @eval M.f(2,3) end t2 = @async begin sleep(1) @time 2 + 2 end end after_comp, after_recomp = Base.cumulative_compile_time_ns() # no need to turn timing off, @time will do that @test after_comp >= before_comp; @test after_recomp >= before_recomp; @test after_recomp - before_recomp <= after_comp - before_comp; # should be approximately 60,000,000 ns, we definitely shouldn't exceed 100x that value # failing this probably means an uninitialized variable somewhere @test after_comp - before_comp < 6_000_000_000; end # redirect_stdout # issue #48024, avoid overcounting timers begin double(x::Real) = 2x; calldouble(container) = double(container[1]); calldouble2(container) = calldouble(container); Base.Experimental.@force_compile; local elapsed = Base.time_ns(); Base.cumulative_compile_timing(true); local compiles = Base.cumulative_compile_time_ns(); @eval calldouble([1.0]); Base.cumulative_compile_timing(false); compiles = Base.cumulative_compile_time_ns() .- compiles; elapsed = Base.time_ns() - elapsed; # compile time should be at most total time @test compiles[1] <= elapsed # recompile time should be at most compile time @test compiles[2] <= compiles[1] elapsed = Base.time_ns(); Base.cumulative_compile_timing(true); compiles = Base.cumulative_compile_time_ns(); @eval calldouble(1.0); Base.cumulative_compile_timing(false); compiles = Base.cumulative_compile_time_ns() .- compiles; elapsed = Base.time_ns() - elapsed; # compile time should be at most total time @test compiles[1] <= elapsed # recompile time should be at most compile time @test compiles[2] <= compiles[1] end macro capture_stdout(ex) quote mktemp() do fname, f redirect_stdout(f) do $(esc(ex)) end seekstart(f) read(f, String) end end end # issue #48024, but with the time macro itself begin double(x::Real) = 2x; calldouble(container) = double(container[1]); calldouble2(container) = calldouble(container); local first = @capture_stdout @time @eval calldouble([1.0]) local second = @capture_stdout @time @eval calldouble2(1.0) # these functions were not recompiled local matches = collect(eachmatch(r"(\d+(?:\.\d+)?)%", first)) @test length(matches) == 1 @test parse(Float64, matches[1][1]) > 0.0 @test parse(Float64, matches[1][1]) <= 100.0 matches = collect(eachmatch(r"(\d+(?:\.\d+)?)%", second)) @test length(matches) == 1 @test parse(Float64, matches[1][1]) > 0.0 @test parse(Float64, matches[1][1]) <= 100.0 end # compilation reports in @time, @timev let f = gensym("f"), callf = gensym("callf"), call2f = gensym("call2f") @eval begin $f(::Real) = 1 $callf(container) = $f(container[1]) $call2f(container) = $callf(container) c64 = [1.0] c32 = [1.0f0] cabs = AbstractFloat[1.0] out = @capture_stdout @time $call2f(c64) @test occursin("% compilation time", out) out = @capture_stdout @time $call2f(c64) @test occursin("% compilation time", out) == false out = @capture_stdout @time $call2f(c32) @test occursin("% compilation time", out) out = @capture_stdout @time $call2f(c32) @test occursin("% compilation time", out) == false out = @capture_stdout @time $call2f(cabs) @test occursin("% compilation time", out) out = @capture_stdout @time $call2f(cabs) @test occursin("% compilation time", out) == false $f(::Float64) = 2 out = @capture_stdout @time $call2f(c64) @test occursin("% compilation time:", out) @test occursin("% of which was recompilation", out) end end let f = gensym("f"), callf = gensym("callf"), call2f = gensym("call2f") @eval begin $f(::Real) = 1 $callf(container) = $f(container[1]) $call2f(container) = $callf(container) c64 = [1.0] c32 = [1.0f0] cabs = AbstractFloat[1.0] out = @capture_stdout @timev $call2f(c64) @test occursin("% compilation time", out) out = @capture_stdout @timev $call2f(c64) @test occursin("% compilation time", out) == false out = @capture_stdout @timev $call2f(c32) @test occursin("% compilation time", out) out = @capture_stdout @timev $call2f(c32) @test occursin("% compilation time", out) == false out = @capture_stdout @timev $call2f(cabs) @test occursin("% compilation time", out) out = @capture_stdout @timev $call2f(cabs) @test occursin("% compilation time", out) == false $f(::Float64) = 2 out = @capture_stdout @timev $call2f(c64) @test occursin("% compilation time:", out) @test occursin("% of which was recompilation", out) end end # interactive utilities struct ambigconvert; end # inject a problematic `convert` method to ensure it still works Base.convert(::Any, v::ambigconvert) = v import Base.summarysize @test summarysize(Core) > (summarysize(Core.Compiler) + Base.summarysize(Core.Intrinsics)) > Core.sizeof(Core) @test summarysize(Base) > 100_000 * sizeof(Ptr) let R = Ref{Any}(nothing), depth = 10^6 for i = 1:depth R = Ref{Any}(R) end R = Core.svec(R, R) @test summarysize(R) == (depth + 4) * sizeof(Ptr) end # issue #25367 - summarysize with reshaped arrays let A = zeros(1000), B = reshape(A, (1,1000)) @test summarysize((A,B)) < 2 * sizeof(A) # check that object header is accounted for @test summarysize(A) > sizeof(A) end # issue #32881 mutable struct S32881; end let s = "abc" @test summarysize([s,s]) < summarysize(["abc","xyz"]) end @test summarysize(Vector{Union{Nothing,Missing}}(undef, 16)) < summarysize(Vector{Union{Nothing,Missing}}(undef, 32)) @test summarysize(Vector{Nothing}(undef, 16)) == summarysize(Vector{Nothing}(undef, 32)) @test summarysize(S32881()) == sizeof(Int) # issue #33675 let vec = vcat(missing, ones(100000)) @test length(unique(summarysize(vec) for i = 1:20)) == 1 end # issue #40773 let s = Set(1:100) @test summarysize([s]) > summarysize(s) end # issue #44780 @test summarysize(BigInt(2)^1000) > summarysize(BigInt(2)) ## test conversion from UTF-8 to UTF-16 (for Windows APIs) # empty arrays @test transcode(UInt16, UInt8[]) == UInt16[] @test transcode(UInt8, UInt16[]) == UInt8[] # UTF-8-like sequences V8 = [ # 1-byte (ASCII) ([0x00],[0x0000]) ([0x0a],[0x000a]) ([0x7f],[0x007f]) # 2-byte ([0xc0,0x80],[0x0000]) # overlong encoding ([0xc1,0xbf],[0x007f]) # overlong encoding ([0xc2,0x80],[0x0080]) ([0xc3,0xbf],[0x00ff]) ([0xc4,0x80],[0x0100]) ([0xc4,0xa3],[0x0123]) ([0xdf,0xbf],[0x07ff]) # 3-byte ([0xe0,0x80,0x80],[0x0000]) # overlong encoding ([0xe0,0x81,0xbf],[0x007f]) # overlong encoding ([0xe0,0x82,0x80],[0x0080]) # overlong encoding ([0xe0,0x9f,0xbf],[0x07ff]) # overlong encoding ([0xe0,0xa0,0x80],[0x0800]) ([0xe0,0xa2,0x9a],[0x089a]) ([0xe1,0x88,0xb4],[0x1234]) ([0xea,0xaf,0x8d],[0xabcd]) ([0xed,0x9f,0xbf],[0xd7ff]) ([0xed,0xa0,0x80],[0xd800]) # invalid code point – high surrogate ([0xed,0xaf,0xbf],[0xdbff]) # invalid code point – high surrogate ([0xed,0xb0,0x80],[0xdc00]) # invalid code point – low surrogate ([0xed,0xbf,0xbf],[0xdfff]) # invalid code point – low surrogate ([0xee,0x80,0x80],[0xe000]) ([0xef,0xbf,0xbf],[0xffff]) # 4-byte ([0xf0,0x80,0x80,0x80],[0x0000]) # overlong encoding ([0xf0,0x80,0x81,0xbf],[0x007f]) # overlong encoding ([0xf0,0x80,0x82,0x80],[0x0080]) # overlong encoding ([0xf0,0x80,0x9f,0xbf],[0x07ff]) # overlong encoding ([0xf0,0x80,0xa0,0x80],[0x0800]) # overlong encoding ([0xf0,0x8f,0xbf,0xbf],[0xffff]) # overlong encoding ([0xf0,0x90,0x80,0x80],[0xd800,0xdc00]) # U+10000 ([0xf0,0x90,0x8d,0x88],[0xd800,0xdf48]) # U+10348 ([0xf0,0x90,0x90,0xb7],[0xd801,0xdc37]) # U+10437 ([0xf0,0xa4,0xad,0xa2],[0xd852,0xdf62]) # U+24b62 ([0xf2,0xab,0xb3,0x9e],[0xda6f,0xdcde]) # U+abcde ([0xf3,0xbf,0xbf,0xbf],[0xdbbf,0xdfff]) # U+fffff ([0xf4,0x80,0x80,0x80],[0xdbc0,0xdc00]) # U+100000 ([0xf4,0x8a,0xaf,0x8d],[0xdbea,0xdfcd]) # U+10abcd ([0xf4,0x8f,0xbf,0xbf],[0xdbff,0xdfff]) # U+10ffff ] # non UTF-8-like sequences X8 = Vector{UInt8}[ # invalid 1-byte sequences [0x80], # 1 leading ones [0xbf], [0xc0], # 2 leading ones [0xdf], [0xe0], # 3 leading ones [0xef], [0xf0], # 4 leading ones [0xf7], [0xf8], # 5 leading ones [0xfb], [0xfc], # 6 leading ones [0xfd], [0xfe], # 7 leading ones [0xff], # 8 leading ones # other invalid sequences [0xf4,0x90,0xbf,0xbf], [0xf4,0x91,0x80,0x80], [0xf7,0x80,0x80,0x80], [0xf7,0xbf,0xbf,0xbf], [0xf8,0x80,0x80,0x80], [0xf8,0xbf,0xbf,0xbf], [0xff,0x80,0x80,0x80], [0xff,0xbf,0xbf,0xbf], ] for s in [map(first,V8); X8], i = 1:length(s)-1, j = i+1:length(s)-(i==1) ss = s[i:j] ss in X8 || push!(X8, ss) end sort!(X8, lt=isless) sort!(X8, by=length) I8 = [(s,map(UInt16,s)) for s in X8] for (X,Y,Z) in ((V8,V8,V8), (I8,V8,I8), (V8,I8,V8), (V8,V8,I8), (I8,V8,V8)) for (a8, a16) in X @test transcode(UInt16, a8) == a16 for (b8, b16) in Y ab8 = [a8; b8] ab16 = [a16; b16] @test transcode(UInt16, ab8) == ab16 for (c8, c16) in Z abc8 = [ab8; c8] abc16 = [ab16; c16] @test transcode(UInt16, abc8) == abc16 end end end end # UTF-16-like sequences V16 = [ # 1-unit UTF-16, 1-byte UTF-8 (ASCII) ([0x0000],[0x00]) ([0x000a],[0x0a]) ([0x007f],[0x7f]) # 1-unit UTF-16, 2-byte UTF-8 ([0x0080],[0xc2,0x80]) ([0x00ff],[0xc3,0xbf]) ([0x0100],[0xc4,0x80]) ([0x0123],[0xc4,0xa3]) ([0x07ff],[0xdf,0xbf]) # 1-unit UTF-16, 3-byte UTF-8 ([0x0800],[0xe0,0xa0,0x80]) ([0x089a],[0xe0,0xa2,0x9a]) ([0x1234],[0xe1,0x88,0xb4]) ([0xabcd],[0xea,0xaf,0x8d]) ([0xd7ff],[0xed,0x9f,0xbf]) ([0xe000],[0xee,0x80,0x80]) ([0xffff],[0xef,0xbf,0xbf]) # 2-unit UTF-16, 4-byte UTF-8 ([0xd800,0xdc00],[0xf0,0x90,0x80,0x80]) # U+10000 ([0xd800,0xdf48],[0xf0,0x90,0x8d,0x88]) # U+10348 ([0xd801,0xdc37],[0xf0,0x90,0x90,0xb7]) # U+10437 ([0xd852,0xdf62],[0xf0,0xa4,0xad,0xa2]) # U+24b62 ([0xda6f,0xdcde],[0xf2,0xab,0xb3,0x9e]) # U+abcde ([0xdbbf,0xdfff],[0xf3,0xbf,0xbf,0xbf]) # U+fffff ([0xdbc0,0xdc00],[0xf4,0x80,0x80,0x80]) # U+100000 ([0xdbea,0xdfcd],[0xf4,0x8a,0xaf,0x8d]) # U+10abcd ([0xdbff,0xdfff],[0xf4,0x8f,0xbf,0xbf]) # U+10ffff ] I16 = [ ([0xd800],[0xed,0xa0,0x80]) # high surrogate ([0xdbff],[0xed,0xaf,0xbf]) # high surrogate ([0xdc00],[0xed,0xb0,0x80]) # low surrogate ([0xdfff],[0xed,0xbf,0xbf]) # low surrogate ] for (X,Y,Z) in ((V16,V16,V16), (I16,V16,I16), (V16,I16,V16), (V16,V16,I16), (I16,V16,V16)) for (a16, a8) in X @test transcode(UInt8, a16) == a8 @test transcode(UInt16, a8) == a16 for (b16, b8) in Y ab16 = [a16; b16] ab8 = [a8; b8] @test transcode(UInt8, ab16) == ab8 @test transcode(UInt16, ab8) == ab16 for (c16, c8) in Z abc16 = [ab16; c16] abc8 = [ab8; c8] @test transcode(UInt8, abc16) == abc8 @test transcode(UInt16, abc8) == abc16 end end end end let s = "abcα🐨\0x\0" for T in (UInt8, UInt16, UInt32, Int32) @test transcode(T, s) == transcode(T, codeunits(s)) @test transcode(String, transcode(T, s)) == s end end let X = UInt8[0x30,0x31,0x32] for T in (UInt8, UInt16, UInt32, Int32) @test transcode(UInt8,transcode(T, X)) == X @test transcode(UInt8,transcode(T, 0x30:0x32)) == X end end let optstring = repr("text/plain", Base.JLOptions()) @test startswith(optstring, "JLOptions(\n") @test !occursin("Ptr{UInt8}", optstring) @test endswith(optstring, "\n)") @test occursin(" = \"", optstring) end let optstring = repr(Base.JLOptions()) @test startswith(optstring, "JLOptions(") @test endswith(optstring, ")") @test !occursin("\n", optstring) @test !occursin("Ptr{UInt8}", optstring) @test occursin(" = \"", optstring) end # Base.securezero! functions (#17579) import Base: securezero!, unsafe_securezero! let a = [1,2,3] @test securezero!(a) === a == [0,0,0] a[:] = 1:3 @test unsafe_securezero!(pointer(a), length(a)) == pointer(a) @test a == [0,0,0] a[:] = 1:3 @test unsafe_securezero!(Ptr{Cvoid}(pointer(a)), sizeof(a)) == Ptr{Cvoid}(pointer(a)) @test a == [0,0,0] end # PR #28038 (prompt/getpass stream args) @test_throws MethodError Base.getpass(IOBuffer(), stdout, "pass") let buf = IOBuffer() @test Base.prompt(IOBuffer("foo\nbar\n"), buf, "baz") == "foo" @test String(take!(buf)) == "baz: " @test Base.prompt(IOBuffer("\n"), buf, "baz", default="foobar") == "foobar" @test String(take!(buf)) == "baz [foobar]: " @test Base.prompt(IOBuffer("blah\n"), buf, "baz", default="foobar") == "blah" end # these tests are not in a test block so that they will compile separately @static if Sys.iswindows() SetLastError(code) = ccall(:SetLastError, stdcall, Cvoid, (UInt32,), code) else SetLastError(_) = nothing end @test Libc.errno(0xc0ffee) === nothing @test SetLastError(0xc0def00d) === nothing let finalized = false function closefunc(_) Libc.errno(0) SetLastError(0) finalized = true end @eval (finalizer($closefunc, zeros()); nothing) GC.gc(); GC.gc(); GC.gc(); GC.gc() @test finalized end @static if Sys.iswindows() @test ccall(:GetLastError, stdcall, UInt32, ()) == 0xc0def00d @test Libc.GetLastError() == 0xc0def00d end @test Libc.errno() == 0xc0ffee # Test that we can VirtualProtect jitted code to writable @noinline function WeVirtualProtectThisToRWX(x, y) return x + y end @static if Sys.iswindows() let addr = @cfunction(WeVirtualProtectThisToRWX, UInt64, (UInt64, UInt64)) addr = addr - (UInt64(addr) % 4096) PAGE_EXECUTE_READWRITE = 0x40 oldPerm = Ref{UInt32}() err18083 = ccall(:VirtualProtect, stdcall, Cint, (Ptr{Cvoid}, Csize_t, UInt32, Ptr{UInt32}), addr, 4096, PAGE_EXECUTE_READWRITE, oldPerm) err18083 == 0 && Base.windowserror(:VirtualProtect) end end let buf = IOBuffer() printstyled(IOContext(buf, :color=>true), "foo", color=:red) @test startswith(String(take!(buf)), Base.text_colors[:red]) end # Test that `printstyled` accepts non-string values, just as `print` does let buf_color = IOBuffer() args = (3.2, "foo", :testsym) printstyled(IOContext(buf_color, :color=>true), args..., color=:red) buf_plain = IOBuffer() print(buf_plain, args...) expected_str = string(Base.text_colors[:red], String(take!(buf_plain)), Base.text_colors[:default]) @test expected_str == String(take!(buf_color)) end # Test that `printstyled` on multiline input prints the ANSI codes # on each line let buf_color = IOBuffer() str = "Two\nlines" printstyled(IOContext(buf_color, :color=>true), str; bold=true, color=:red) @test String(take!(buf_color)) == "\e[31m\e[1mTwo\e[22m\e[39m\n\e[31m\e[1mlines\e[22m\e[39m" end if stdout isa Base.TTY @test haskey(stdout, :color) == true @test haskey(stdout, :bar) == false @test (:color=>Base.have_color) in stdout @test (:color=>!Base.have_color) ∉ stdout @test stdout[:color] == get(stdout, :color, nothing) == Base.have_color @test get(stdout, :bar, nothing) === nothing @test_throws KeyError stdout[:bar] end @testset "`displaysize` on closed TTY #34620" begin Main.FakePTYs.with_fake_pty() do rawfd, _ tty = open(rawfd)::Base.TTY @test displaysize(tty) isa Tuple{Integer,Integer} close(tty) @test_throws Base.IOError displaysize(tty) end end let global c_18711 = 0 buf = IOContext(IOBuffer(), :hascontext => true) Base.with_output_color(:red, buf) do buf global c_18711 get(buf, :hascontext, false) && (c_18711 += 1) end @test c_18711 == 1 end let buf = IOBuffer() buf_color = IOContext(buf, :color => true) printstyled(buf_color, "foo", color=:red) # Check that we get back to normal text color in the end @test String(take!(buf)) == "\e[31mfoo\e[39m" # Check that boldness is turned off printstyled(buf_color, "foo"; bold=true, color=:red) @test String(take!(buf)) == "\e[31m\e[1mfoo\e[22m\e[39m" # Check that italic is turned off printstyled(buf_color, "foo"; italic=true, color=:red) @test String(take!(buf)) == "\e[31m\e[3mfoo\e[23m\e[39m" # Check that underline is turned off printstyled(buf_color, "foo"; color = :red, underline = true) @test String(take!(buf)) == "\e[31m\e[4mfoo\e[24m\e[39m" # Check that blink is turned off printstyled(buf_color, "foo"; color = :red, blink = true) @test String(take!(buf)) == "\e[31m\e[5mfoo\e[25m\e[39m" # Check that reverse is turned off printstyled(buf_color, "foo"; color = :red, reverse = true) @test String(take!(buf)) == "\e[31m\e[7mfoo\e[27m\e[39m" # Check that hidden is turned off printstyled(buf_color, "foo"; color = :red, hidden = true) @test String(take!(buf)) == "\e[31m\e[8mfoo\e[28m\e[39m" # Check that all options can be turned on simultaneously printstyled(buf_color, "foo"; color = :red, bold = true, italic = true, underline = true, blink = true, reverse = true, hidden = true) @test String(take!(buf)) == "\e[31m\e[1m\e[3m\e[4m\e[5m\e[7m\e[8mfoo\e[28m\e[27m\e[25m\e[24m\e[22m\e[23m\e[39m" end abstract type DA_19281{T, N} <: AbstractArray{T, N} end Base.convert(::Type{Array{S, N}}, ::DA_19281{T, N}) where {S,T,N} = error() x_19281 = [(), (1,)] mutable struct Foo_19281 f::Vector{Tuple} Foo_19281() = new(x_19281) end @testset "test this does not segfault #19281" begin @test Foo_19281().f[1] == () @test Foo_19281().f[2] == (1,) end let x_notdefined = Ref{String}() @test !isassigned(x_notdefined) x_defined = Ref{String}("Test") @test isassigned(x_defined) end mutable struct Demo_20254 arr::Array{String} end # these cause stack overflows and are a little flaky on CI, ref #20256 if Base.get_bool_env("JULIA_TESTFULL", false) function Demo_20254(arr::AbstractArray=Any[]) Demo_20254(string.(arr)) end _get_19433(x::NTuple{1}) = (something(x[1]),) _get_19433(xs::Vararg) = (something(xs[1]), _get_19433(xs[2:end])...) f_19433(f_19433, xs...) = f_19433(_get_19433(xs)...) @testset "test this does not crash, issue #19433 and #20254" begin @test_throws StackOverflowError Demo_20254() @test_throws StackOverflowError f_19433(+, 1, 2) end end # Test issue #19774 invokelatest fix. # we define this in a module to allow rewriting # rather than needing an extra eval. module Issue19774 f(x) = 1 end # First test the world issue condition. let foo() = begin @eval Issue19774.f(x::Int) = 2 return Issue19774.f(0) end @test foo() == 1 # We should be using the original function. end # Now check that invokelatest fixes that issue. let foo() = begin @eval Issue19774.f(x::Int) = 3 return Base.invokelatest(Issue19774.f, 0) end @test foo() == 3 end # Check that the kwargs conditions also works module Kwargs19774 f(x, y; z=0) = x * y + z end @test Kwargs19774.f(2, 3; z=1) == 7 let foo() = begin @eval Kwargs19774.f(x::Int, y::Int; z=3) = z return Base.invokelatest(Kwargs19774.f, 2, 3; z=1) end @test foo() == 1 end module atinvokelatest f(x) = 1 g(x, y; z=0) = x * y + z mutable struct X; x; end Base.getproperty(::X, ::Any) = error("overload me") Base.setproperty!(::X, ::Any, ::Any) = error("overload me") struct Xs xs::Vector{Any} end Base.getindex(::Xs, ::Any) = error("overload me") Base.setindex!(::Xs, ::Any, ::Any) = error("overload me") end let call_test() = begin @eval atinvokelatest.f(x::Int) = 3 return @invokelatest atinvokelatest.f(0) end @test call_test() == 3 call_with_kws_test() = begin @eval atinvokelatest.g(x::Int, y::Int; z=3) = z return @invokelatest atinvokelatest.g(2, 3; z=1) end @test call_with_kws_test() == 1 getproperty_test() = begin @eval Base.getproperty(x::atinvokelatest.X, f::Symbol) = getfield(x, f) x = atinvokelatest.X(nothing) return @invokelatest x.x end @test isnothing(getproperty_test()) setproperty!_test() = begin @eval Base.setproperty!(x::atinvokelatest.X, f::Symbol, @nospecialize(v)) = setfield!(x, f, v) x = atinvokelatest.X(nothing) @invokelatest x.x = 1 return x end x = setproperty!_test() @test getfield(x, :x) == 1 getindex_test() = begin @eval Base.getindex(xs::atinvokelatest.Xs, idx::Int) = xs.xs[idx] xs = atinvokelatest.Xs(Any[nothing]) return @invokelatest xs[1] end @test isnothing(getindex_test()) setindex!_test() = begin @eval function Base.setindex!(xs::atinvokelatest.Xs, @nospecialize(v), idx::Int) xs.xs[idx] = v end xs = atinvokelatest.Xs(Any[nothing]) @invokelatest xs[1] = 1 return xs end xs = setindex!_test() @test xs.xs[1] == 1 end abstract type InvokeX end Base.getproperty(::InvokeX, ::Symbol) = error("overload InvokeX") Base.setproperty!(::InvokeX, ::Symbol, @nospecialize(v::Any)) = error("overload InvokeX") mutable struct InvokeX2 <: InvokeX; x; end Base.getproperty(x::InvokeX2, f::Symbol) = getfield(x, f) Base.setproperty!(x::InvokeX2, f::Symbol, @nospecialize(v::Any)) = setfield!(x, f, v) abstract type InvokeXs end Base.getindex(::InvokeXs, ::Int) = error("overload InvokeXs") Base.setindex!(::InvokeXs, @nospecialize(v::Any), ::Int) = error("overload InvokeXs") struct InvokeXs2 <: InvokeXs xs::Vector{Any} end Base.getindex(xs::InvokeXs2, idx::Int) = xs.xs[idx] Base.setindex!(xs::InvokeXs2, @nospecialize(v::Any), idx::Int) = xs.xs[idx] = v @testset "@invoke macro" begin # test against `invoke` doc example let f(x::Real) = x^2 f(x::Integer) = 1 + @invoke f(x::Real) @test f(2) == 5 end let f1(::Integer) = Integer f1(::Real) = Real; f2(x::Real) = _f2(x) _f2(::Integer) = Integer _f2(_) = Real @test f1(1) === Integer @test f2(1) === Integer @test @invoke(f1(1::Real)) === Real @test @invoke(f2(1::Real)) === Integer end # when argument's type annotation is omitted, it should be specified as `Core.Typeof(x)` let f(_) = Any f(x::Integer) = Integer @test f(1) === Integer @test @invoke(f(1::Any)) === Any @test @invoke(f(1)) === Integer 😎(x, y) = 1 😎(x, ::Type{Int}) = 2 # Without `Core.Typeof`, the first method would be called @test @invoke(😎(1, Int)) == 2 end # handle keyword arguments correctly let f(a; kw1 = nothing, kw2 = nothing) = a + max(kw1, kw2) f(::Integer; kwargs...) = error("don't call me") @test_throws Exception f(1; kw1 = 1, kw2 = 2) @test 3 == @invoke f(1::Any; kw1 = 1, kw2 = 2) end # additional syntax test let x = InvokeX2(nothing) @test_throws "overload InvokeX" @invoke (x::InvokeX).x @test isnothing(@invoke x.x) @test_throws "overload InvokeX" @invoke (x::InvokeX).x = 42 @invoke x.x = 42 @test 42 == x.x xs = InvokeXs2(Any[nothing]) @test_throws "overload InvokeXs" @invoke (xs::InvokeXs)[1] @test isnothing(@invoke xs[1]) @test_throws "overload InvokeXs" @invoke (xs::InvokeXs)[1] = 42 @invoke xs[1] = 42 @test 42 == xs.xs[1] end end # Endian tests # For now, we only support little endian. # Add an `Sys.ARCH` test for big endian when/if we add support for that. # Do **NOT** use `ENDIAN_BOM` to figure out the endianness # since that's exactly what we want to test. @test ENDIAN_BOM == 0x04030201 @test ntoh(0x1) == 0x1 @test hton(0x1) == 0x1 @test ltoh(0x1) == 0x1 @test htol(0x1) == 0x1 @test ntoh(0x102) == 0x201 @test hton(0x102) == 0x201 @test ltoh(0x102) == 0x102 @test htol(0x102) == 0x102 @test ntoh(0x1020304) == 0x4030201 @test hton(0x1020304) == 0x4030201 @test ltoh(0x1020304) == 0x1020304 @test htol(0x1020304) == 0x1020304 @test ntoh(0x102030405060708) == 0x807060504030201 @test hton(0x102030405060708) == 0x807060504030201 @test ltoh(0x102030405060708) == 0x102030405060708 @test htol(0x102030405060708) == 0x102030405060708 @testset "inline bug #18735" begin @noinline f(n) = n ? error() : Int g() = Union{f(true)} @test_throws ErrorException g() end include("testenv.jl") let flags = Cmd(filter(a->!occursin("depwarn", a), collect(test_exeflags))) local cmd = `$test_exename $flags --depwarn=yes deprecation_exec.jl` if !success(pipeline(cmd; stdout=stdout, stderr=stderr)) error("Deprecation test failed, cmd : $cmd") end end # PR #23664, make sure names don't get added to the default `Main` workspace @test readlines(`$(Base.julia_cmd()) --startup-file=no -e 'foreach(println, names(Main))'`) == ["Base","Core","Main"] # issue #26310 @test_warn "could not import" Core.eval(@__MODULE__, :(import .notdefined_26310__)) @test_warn "could not import" Core.eval(Main, :(import ........notdefined_26310__)) @test_nowarn Core.eval(Main, :(import .Main)) @test_nowarn Core.eval(Main, :(import ....Main)) # issue #27239 using Base.BinaryPlatforms: HostPlatform, libc @testset "strftime tests issue #27239" begin # change to non-Unicode Korean to test that it is properly transcoded into valid UTF-8 korloc = ["ko_KR.EUC-KR", "ko_KR.CP949", "ko_KR.949", "Korean_Korea.949"] at_least_one_locale_found = false withlocales(korloc) do locale at_least_one_locale_found = true # Test both the default format and a custom formatting string for s in (Libc.strftime(0.0), Libc.strftime("%a %A %b %B %p %Z", 0)) # Ensure that we always get valid UTF-8 back @test isvalid(s) # On `musl` it is impossible for `setlocale` to fail, it just falls back to # the default system locale, which on our buildbots is en_US.UTF-8. We'll # assert that what we get does _not_ start with `Thu`, as that's what all # en_US.UTF-8 encodings would start with. # X-ref: https://musl.openwall.narkive.com/kO1vpTWJ/setlocale-behavior-with-missing-locales @test !startswith(s, "Thu") broken=(libc(HostPlatform()) == "musl") end end if !at_least_one_locale_found @warn "skipping stftime tests: no locale found for testing" end end using Base: @kwdef @kwdef struct Test27970Typed a::Int b::String = "hi" end @kwdef struct Test27970Untyped a end @kwdef struct Test27970Empty end @testset "No default values in @kwdef" begin @test Test27970Typed(a=1) == Test27970Typed(1, "hi") # Implicit type conversion (no assertion on kwarg) @test Test27970Typed(a=0x03) == Test27970Typed(3, "hi") @test_throws UndefKeywordError Test27970Typed() @test Test27970Untyped(a=1) == Test27970Untyped(1) @test_throws UndefKeywordError Test27970Untyped() # Just checking that this doesn't stack overflow on construction @test Test27970Empty() == Test27970Empty() end abstract type AbstractTest29307 end @kwdef struct Test29307{T<:Integer} <: AbstractTest29307 a::T=2 end @testset "subtyped @kwdef" begin @test Test29307() == Test29307{Int}(2) @test Test29307(a=0x03) == Test29307{UInt8}(0x03) @test Test29307{UInt32}() == Test29307{UInt32}(2) @test Test29307{UInt32}(a=0x03) == Test29307{UInt32}(0x03) end @kwdef struct TestInnerConstructor a = 1 TestInnerConstructor(a::Int) = (@assert a>0; new(a)) function TestInnerConstructor(a::String) @assert length(a) > 0 new(a) end end @testset "@kwdef inner constructor" begin @test TestInnerConstructor() == TestInnerConstructor(1) @test TestInnerConstructor(a=2) == TestInnerConstructor(2) @test_throws AssertionError TestInnerConstructor(a=0) @test TestInnerConstructor(a="2") == TestInnerConstructor("2") @test_throws AssertionError TestInnerConstructor(a="") end const outsidevar = 7 @kwdef struct TestOutsideVar a::Int=outsidevar end @test TestOutsideVar() == TestOutsideVar(7) @kwdef mutable struct Test_kwdef_const_atomic a b::Int c::Int = 1 const d const e::Int const f = 1 const g::Int = 1 @atomic h::Int end @testset "const and @atomic fields in @kwdef" begin x = Test_kwdef_const_atomic(a = 1, b = 1, d = 1, e = 1, h = 1) for f in fieldnames(Test_kwdef_const_atomic) @test getfield(x, f) == 1 end @testset "const fields" begin @test_throws ErrorException x.d = 2 @test_throws ErrorException x.e = 2 @test_throws MethodError x.e = "2" @test_throws ErrorException x.f = 2 @test_throws ErrorException x.g = 2 end @testset "atomic fields" begin @test_throws ConcurrencyViolationError x.h = 1 @atomic x.h = 1 @test @atomic(x.h) == 1 @atomic x.h = 2 @test @atomic(x.h) == 2 end end @kwdef struct Test_kwdef_lineinfo a::String end @testset "@kwdef constructor line info" begin for method in methods(Test_kwdef_lineinfo) @test method.file === Symbol(@__FILE__) @test ((@__LINE__)-6) ≤ method.line ≤ ((@__LINE__)-5) end end @kwdef struct Test_kwdef_lineinfo_sparam{S<:AbstractString} a::S end @testset "@kwdef constructor line info with static parameter" begin for method in methods(Test_kwdef_lineinfo_sparam) @test method.file === Symbol(@__FILE__) @test ((@__LINE__)-6) ≤ method.line ≤ ((@__LINE__)-5) end end @testset "exports of modules" begin for (_, mod) in Base.loaded_modules mod === Main && continue # Main exports everything for v in names(mod) @test isdefined(mod, v) end end end @testset "ordering UUIDs" begin a = Base.UUID("dbd321ed-e87e-4f33-9511-65b7d01cdd55") b = Base.UUID("2832b20a-2ad5-46e9-abb1-2d20c8c31dd3") @test isless(b, a) @test sort([a, b]) == [b, a] end @testset "UUID display" begin a = Base.UUID("dbd321ed-e87e-4f33-9511-65b7d01cdd55") @test repr(a) == "$(Base.UUID)(\"dbd321ed-e87e-4f33-9511-65b7d01cdd55\")" end @testset "Libc.rand" begin low, high = extrema(Libc.rand(Float64) for i=1:10^4) # these fail with probability 2^(-10^4) ≈ 5e-3011 @test 0 ≤ low < 0.5 @test 0.5 < high < 1 end # Pointer 0-arg constructor @test Ptr{Cvoid}() == C_NULL @testset "Pointer to unsigned/signed integer" begin # assuming UInt and Ptr have the same size @assert sizeof(UInt) == sizeof(Ptr{Nothing}) uint = UInt(0x12345678) sint = signed(uint) ptr = reinterpret(Ptr{Nothing}, uint) @test unsigned(ptr) === uint @test signed(ptr) === sint end # Finalizer with immutable should throw @test_throws ErrorException finalizer(x->nothing, 1) @test_throws ErrorException finalizer(C_NULL, 1) @testset "GC utilities" begin GC.gc() GC.gc(true); GC.gc(false) GC.safepoint() mktemp() do tmppath, _ open(tmppath, "w") do tmpio redirect_stderr(tmpio) do GC.enable_logging(true) GC.gc() GC.enable_logging(false) end end @test occursin("GC: pause", read(tmppath, String)) end end @testset "fieldtypes Module" begin @test fieldtypes(Module) === () end @testset "issue #28188" begin @test `$(@__FILE__)` == let file = @__FILE__; `$file` end end # Test that read fault on a prot-none region does not incorrectly give # ReadOnlyMemoryError, but rather crashes the program const MAP_ANONYMOUS_PRIVATE = Sys.isbsd() ? 0x1002 : 0x22 let script = :( let ptr = Ptr{Cint}(ccall(:jl_mmap, Ptr{Cvoid}, (Ptr{Cvoid}, Csize_t, Cint, Cint, Cint, Int), C_NULL, 16*1024, 0, $MAP_ANONYMOUS_PRIVATE, -1, 0)) try unsafe_load(ptr) catch e println(e) end end ) cmd = if Sys.isunix() # Set the maximum core dump size to 0 to keep this expected crash from # producing a (and potentially overwriting an existing) core dump file `sh -c "ulimit -c 0; $(Base.shell_escape(Base.julia_cmd())) -e '$script'"` else `$(Base.julia_cmd()) -e '$script'` end @test !success(cmd) end # issue #41656 @test success(`$(Base.julia_cmd()) -e 'isempty(x) = true'`) @testset "Base/timing.jl" begin @test Base.jit_total_bytes() >= 0 # sanity check `@allocations` returns what we expect in some very simple cases @test (@allocations "a") == 0 @test (@allocations "a" * "b") == 0 # constant propagation @test (@allocations "a" * Base.inferencebarrier("b")) == 1 end @testset "in_finalizer" begin @test !GC.in_finalizer() in_fin = Ref{Any}() wait(@async begin r = Ref(1) finalizer(r) do _ in_fin[] = GC.in_finalizer() end nothing end) GC.gc(true); yield() @test in_fin[] end @testset "Base docstrings" begin undoc = Docs.undocumented_names(Base) @test_broken isempty(undoc) @test undoc == [:BufferStream, :CanonicalIndexError, :CapturedException, :Filesystem, :IOServer, :InvalidStateException, :Order, :PipeEndpoint, :Sort, :TTY] end @testset "Base.Libc docstrings" begin @test isempty(Docs.undocumented_names(Libc)) end