1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
|
# This file is a part of Julia. License is MIT: https://julialang.org/license
using Test, InteractiveUtils
# test methodswith
# `methodswith` relies on exported symbols
export func4union, Base
struct NoMethodHasThisType end
@test isempty(methodswith(NoMethodHasThisType))
@test !isempty(methodswith(Int))
struct Type4Union end
func4union(::Union{Type4Union,Int}) = ()
@test !isempty(methodswith(Type4Union, @__MODULE__))
# PR #19964
@test isempty(subtypes(Float64))
# Issue #20086
abstract type A20086{T,N} end
struct B20086{T,N} <: A20086{T,N} end
@test subtypes(A20086) == [B20086]
@test subtypes(A20086{Int}) == [B20086{Int}]
@test subtypes(A20086{T,3} where T) == [B20086{T,3} where T]
@test subtypes(A20086{Int,3}) == [B20086{Int,3}]
# code_warntype
module WarnType
using Test, Random, InteractiveUtils
function warntype_hastag(f, types, tag)
iob = IOBuffer()
code_warntype(iob, f, types)
str = String(take!(iob))
return occursin(tag, str)
end
pos_stable(x) = x > 0 ? x : zero(x)
pos_unstable(x) = x > 0 ? x : 0
tag = "UNION"
@test warntype_hastag(pos_unstable, Tuple{Float64}, tag)
@test !warntype_hastag(pos_stable, Tuple{Float64}, tag)
mutable struct Stable{T,N}
A::Array{T,N}
end
mutable struct Unstable{T}
A::Array{T}
end
Base.getindex(A::Stable, i) = A.A[i]
Base.getindex(A::Unstable, i) = A.A[i]
tag = "ARRAY{FLOAT64,N}"
@test warntype_hastag(getindex, Tuple{Unstable{Float64},Int}, tag)
@test !warntype_hastag(getindex, Tuple{Stable{Float64,2},Int}, tag)
@test warntype_hastag(getindex, Tuple{Stable{Float64},Int}, tag)
# Make sure emphasis is not used for other functions
tag = "ANY"
iob = IOBuffer()
show(iob, Meta.lower(Main, :(x -> x^2)))
str = String(take!(iob))
@test !occursin(tag, str)
# Make sure non used variables are not emphasized
has_unused() = (a = rand(5))
@test !warntype_hastag(has_unused, Tuple{}, tag)
# No variable information with the new optimizer. Eventually might be able to recover
# some of this info with debug info.
#@test warntype_hastag(has_unused, Tuple{}, "<optimized out>")
# Make sure that "expected" unions are highlighted with warning color instead of error color
iob = IOBuffer()
code_warntype(IOContext(iob, :color => true), x -> (x > 1 ? "foo" : nothing), Tuple{Int64})
str = String(take!(iob))
@test occursin(Base.text_colors[Base.warn_color()], str)
# Make sure getproperty and setproperty! works with @code_... macros
struct T1234321
t::Int
end
Base.getproperty(t::T1234321, ::Symbol) = "foo"
@test (@code_typed T1234321(1).f).second == String
Base.setproperty!(t::T1234321, ::Symbol, ::Symbol) = "foo"
@test (@code_typed T1234321(1).f = :foo).second == String
module ImportIntrinsics15819
# Make sure changing the lookup path of an intrinsic doesn't break
# the heuristic for type instability warning.
import Core.Intrinsics: sqrt_llvm, bitcast
# Use import
sqrt15819(x::Float64) = bitcast(Float64, sqrt_llvm(x))
# Use fully qualified name
sqrt15819(x::Float32) = bitcast(Float32, Core.Intrinsics.sqrt_llvm(x))
end # module ImportIntrinsics15819
foo11122(x) = @fastmath x - 1.0
# issue #11122, #13568 and #15819
@test !warntype_hastag(+, Tuple{Int,Int}, tag)
@test !warntype_hastag(-, Tuple{Int,Int}, tag)
@test !warntype_hastag(*, Tuple{Int,Int}, tag)
@test !warntype_hastag(/, Tuple{Int,Int}, tag)
@test !warntype_hastag(foo11122, Tuple{Float32}, tag)
@test !warntype_hastag(foo11122, Tuple{Float64}, tag)
@test !warntype_hastag(foo11122, Tuple{Int}, tag)
@test !warntype_hastag(sqrt, Tuple{Int}, tag)
@test !warntype_hastag(sqrt, Tuple{Float64}, tag)
@test !warntype_hastag(^, Tuple{Float64,Int32}, tag)
@test !warntype_hastag(^, Tuple{Float32,Int32}, tag)
@test !warntype_hastag(ImportIntrinsics15819.sqrt15819, Tuple{Float64}, tag)
@test !warntype_hastag(ImportIntrinsics15819.sqrt15819, Tuple{Float32}, tag)
end # module WarnType
# Adds test for PR #17636
let a = @code_typed 1 + 1
b = @code_lowered 1 + 1
@test isa(a, Pair{Core.CodeInfo, DataType})
@test isa(b, Core.CodeInfo)
@test isa(a[1].code, Array{Any,1})
@test isa(b.code, Array{Any,1})
function thing(a::Array, b::Real)
println("thing")
end
function thing(a::AbstractArray, b::Int)
println("blah")
end
@test_throws MethodError thing(rand(10), 1)
a = @code_typed thing(rand(10), 1)
b = @code_lowered thing(rand(10), 1)
@test length(a) == 0
@test length(b) == 0
end
# Issue #16326
mktemp() do f, io
OLDSTDOUT = stdout
redirect_stdout(io)
@test try @code_native map(abs, rand(3)); true; catch; false; end
redirect_stdout(OLDSTDOUT)
nothing
end
module _test_varinfo_
export x
x = 1.0
end
@test repr(varinfo(Main, r"^$")) == """
| name | size | summary |
|:---- | ----:|:------- |
"""
let v = repr(varinfo(_test_varinfo_))
@test occursin("| x | 8 bytes | Float64 |", v)
end
# Issue 14173
module Tmp14173
using Random
export A
A = randn(2000, 2000)
end
varinfo(Tmp14173) # warm up
const MEMDEBUG = ccall(:jl_is_memdebug, Bool, ())
@test @allocated(varinfo(Tmp14173)) < (MEMDEBUG ? 60000 : 20000)
# PR #24997: test that `varinfo` doesn't fail when encountering `missing`
module A
using InteractiveUtils
export missing
varinfo(A)
end
# PR #23075
@testset "versioninfo" begin
# check that versioninfo(io; verbose=true) doesn't error, produces some output
mktempdir() do dir
buf = PipeBuffer()
versioninfo(buf, verbose=true)
ver = read(buf, String)
@test startswith(ver, "Julia Version $VERSION")
@test occursin("Environment:", ver)
end
let exename = `$(Base.julia_cmd()) --startup-file=no`
@test !occursin("Environment:", read(setenv(`$exename -e 'using InteractiveUtils; versioninfo()'`,
String[]), String))
@test occursin("Environment:", read(setenv(`$exename -e 'using InteractiveUtils; versioninfo()'`,
String["JULIA_CPU_THREADS=1"]), String))
end
end
const curmod = @__MODULE__
const curmod_name = fullname(curmod)
const curmod_str = curmod === Main ? "Main" : join(curmod_name, ".")
@test_throws ErrorException("\"this_is_not_defined\" is not defined in module $curmod_str") @which this_is_not_defined
# issue #13264
@test (@which vcat(1...)).name == :vcat
# PR #28122, issue #25474
@test (@which [1][1]).name === :getindex
@test (@which [1][1] = 2).name === :setindex!
@test (@which [1]).name === :vect
@test (@which [1 2]).name === :hcat
@test (@which [1; 2]).name === :vcat
@test (@which Int[1 2]).name === :typed_hcat
@test (@which Int[1; 2]).name === :typed_vcat
@test (@which [1 2;3 4]).name === :hvcat
@test (@which Int[1 2;3 4]).name === :typed_hvcat
# issue #13464
try
@which x = 1
error("unexpected")
catch err13464
@test startswith(err13464.msg, "expression is not a function call, or is too complex")
end
module MacroTest
export @macrotest
macro macrotest(x::Int, y::Symbol) end
macro macrotest(x::Int, y::Int)
nothing #This is here because of #15280
end
end
let
using .MacroTest
a = 1
m = getfield(@__MODULE__, Symbol("@macrotest"))
@test which(m, Tuple{LineNumberNode, Module, Int, Symbol}) == @which @macrotest 1 a
@test which(m, Tuple{LineNumberNode, Module, Int, Int}) == @which @macrotest 1 1
@test first(methods(m, Tuple{LineNumberNode, Module, Int, Int})) == @which MacroTest.@macrotest 1 1
@test functionloc(@which @macrotest 1 1) == @functionloc @macrotest 1 1
end
mutable struct A18434
end
A18434(x; y=1) = 1
global counter18434 = 0
function get_A18434()
global counter18434
counter18434 += 1
return A18434
end
@which get_A18434()(1; y=2)
@test counter18434 == 1
@which get_A18434()(1, y=2)
@test counter18434 == 2
let _true = Ref(true), f, g, h
@noinline f() = ccall((:time, "error_library_doesnt_exist\0"), Cvoid, ()) # some expression that throws an error in codegen
@noinline g() = _true[] ? 0 : h()
@noinline h() = (g(); f())
@test_throws ErrorException @code_native h() # due to a failure to compile f()
@test g() == 0
end
module ReflectionTest
using Test, Random, InteractiveUtils
function test_ast_reflection(freflect, f, types)
@test !isempty(freflect(f, types))
nothing
end
function test_bin_reflection(freflect, f, types)
iob = IOBuffer()
freflect(iob, f, types)
str = String(take!(iob))
@test !isempty(str)
nothing
end
function test_code_reflection(freflect, f, types, tester)
tester(freflect, f, types)
tester(freflect, f, (types.parameters...,))
nothing
end
function test_code_reflections(tester, freflect)
test_code_reflection(freflect, occursin,
Tuple{Regex, AbstractString}, tester) # abstract type
test_code_reflection(freflect, +, Tuple{Int, Int}, tester) # leaftype signature
test_code_reflection(freflect, +,
Tuple{Array{Float32}, Array{Float32}}, tester) # incomplete types
test_code_reflection(freflect, Module, Tuple{}, tester) # Module() constructor (transforms to call)
test_code_reflection(freflect, Array{Int64}, Tuple{Array{Int32}}, tester) # with incomplete types
test_code_reflection(freflect, muladd, Tuple{Float64, Float64, Float64}, tester)
end
test_code_reflections(test_bin_reflection, code_llvm)
test_code_reflections(test_bin_reflection, code_native)
end # module ReflectionTest
@test_throws ArgumentError("argument is not a generic function") code_llvm(===, Tuple{Int, Int})
@test_throws ArgumentError("argument is not a generic function") code_native(===, Tuple{Int, Int})
# Issue #18883, code_llvm/code_native for generated functions
@generated f18883() = nothing
@test !isempty(sprint(code_llvm, f18883, Tuple{}))
@test !isempty(sprint(code_native, f18883, Tuple{}))
ix86 = r"i[356]86"
if Sys.ARCH === :x86_64 || occursin(ix86, string(Sys.ARCH))
function linear_foo()
x = 4
y = 5
end
rgx = r"%"
buf = IOBuffer()
output=""
#test that the string output is at&t syntax by checking for occurrences of '%'s
code_native(buf,linear_foo,(), syntax = :att)
output=String(take!(buf))
@test occursin(rgx, output)
#test that the code output is intel syntax by checking it has no occurrences of '%'
code_native(buf,linear_foo,(), syntax = :intel)
output=String(take!(buf))
@test !occursin(rgx, output)
code_native(buf,linear_foo,())
output=String(take!(buf))
@test occursin(rgx, output)
end
@testset "error message" begin
err = ErrorException("expression is not a function call or symbol")
@test_throws err @code_lowered ""
@test_throws err @code_lowered 1
@test_throws err @code_lowered 1.0
end
using InteractiveUtils: editor
# Issue #13032
withenv("JULIA_EDITOR" => nothing, "VISUAL" => nothing, "EDITOR" => nothing) do
# Make sure editor doesn't error when no ENV editor is set.
@test isa(editor(), Array)
# Invalid editor
ENV["JULIA_EDITOR"] = ""
@test_throws ErrorException editor()
# Note: The following testcases should work regardless of whether these editors are
# installed or not.
# Editor on the path.
ENV["JULIA_EDITOR"] = "vim"
@test editor() == ["vim"]
# Absolute path to editor.
ENV["JULIA_EDITOR"] = "/usr/bin/vim"
@test editor() == ["/usr/bin/vim"]
# Editor on the path using arguments.
ENV["JULIA_EDITOR"] = "subl -w"
@test editor() == ["subl", "-w"]
# Absolute path to editor with spaces.
ENV["JULIA_EDITOR"] = "/Applications/Sublime\\ Text.app/Contents/SharedSupport/bin/subl"
@test editor() == ["/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl"]
# Paths with spaces and arguments (#13032).
ENV["JULIA_EDITOR"] = "/Applications/Sublime\\ Text.app/Contents/SharedSupport/bin/subl -w"
@test editor() == ["/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl", "-w"]
ENV["JULIA_EDITOR"] = "'/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl' -w"
@test editor() == ["/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl", "-w"]
ENV["JULIA_EDITOR"] = "\"/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl\" -w"
@test editor() == ["/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl", "-w"]
end
# clipboard functionality
if Sys.iswindows() || Sys.isapple()
for str in ("Hello, world.", "∀ x ∃ y", "")
clipboard(str)
@test clipboard() == str
end
end
|