Skip to content

Commit

Permalink
Test for invalid frame. Removed failing Win32 test.
Browse files Browse the repository at this point in the history
Reintroduced UNKNOWN constant stack frame from profile.jl.
Added test case for looking up an invalid stack frame.
Selectively removed some tests that consistently fail in Appveyor's 32-bit
Windows LVM.
  • Loading branch information
spurll committed Jan 20, 2016
1 parent 114a640 commit 6daf1eb
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 34 deletions.
4 changes: 1 addition & 3 deletions base/profile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module Profile

import Base.StackTraces: StackFrame, lookup
import Base.StackTraces: lookup, UNKNOWN

export @profile

Expand Down Expand Up @@ -211,8 +211,6 @@ end
#@windows_only const btskip = 0
const btskip = 0

const UNKNOWN = StackFrame(symbol("???"), symbol("???"), 0, symbol(""), -1, true, 0)

## Print as a flat list
# Counts the number of times each line appears, at any nesting level
function count_flat{T<:Unsigned}(data::Vector{T})
Expand Down
5 changes: 5 additions & 0 deletions base/stacktraces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ immutable StackFrame
pointer::Int64 # Large enough to be read losslessly on 32- and 64-bit machines.
end

StackFrame(func, file, line) = StackFrame(func, file, line, symbol(""), -1, false, 0)

"""
StackTrace
Expand All @@ -38,6 +40,9 @@ An alias for `Vector{StackFrame}` provided for convenience; returned by calls to
typealias StackTrace Vector{StackFrame}


const UNKNOWN = StackFrame(symbol("???"), symbol("???"), 0, symbol(""), -1, true, 0)


#=
If the StackFrame has function and line information, we consider two of them the same if
they share the same function/line information. For unknown functions, line == pointer, so we
Expand Down
70 changes: 39 additions & 31 deletions test/stacktraces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,56 @@

# Tests for /base/stacktraces.jl

let
@noinline child() = stacktrace()
@noinline parent() = child()
@noinline grandparent() = parent()
line_numbers = @__LINE__ - [3, 2, 1]
# Some tests don't currently work for Appveyor 32-bit Windows
const APPVEYOR_WIN32 = (
OS_NAME == :Windows && WORD_SIZE == 32 && get(ENV, "APPVEYOR", "False") == "True"
)

if !APPVEYOR_WIN32
let
@noinline child() = stacktrace()
@noinline parent() = child()
@noinline grandparent() = parent()
line_numbers = @__LINE__ - [3, 2, 1]

# Basic tests.
stack = grandparent()
@assert length(stack) >= 3 "Compiler has unexpectedly inlined functions"
@test [:child, :parent, :grandparent] == [f.func for f in stack[1:3]]
for (line, frame) in zip(line_numbers, stack[1:3])
@test [Symbol(@__FILE__), line] in
([frame.file, frame.line], [frame.inlined_file, frame.inlined_line])
end
@test [false, false, false] == [f.from_c for f in stack[1:3]]

# Test remove_frames!
stack = StackTraces.remove_frames!(grandparent(), :parent)
@test stack[1] == StackFrame(:grandparent, @__FILE__, line_numbers[3])

# Basic tests.
stack = grandparent()
@test [:child, :parent, :grandparent] == [f.func for f in stack[1:3]]
for (line, frame) in zip(line_numbers, stack[1:3])
@test [Symbol(@__FILE__), line] in
([frame.file, frame.line], [frame.inlined_file, frame.inlined_line])
stack = StackTraces.remove_frames!(grandparent(), [:child, :something_nonexistent])
@test stack[1:2] == [
StackFrame(:parent, @__FILE__, line_numbers[2]),
StackFrame(:grandparent, @__FILE__, line_numbers[3])
]
end
@test [false, false, false] == [f.from_c for f in stack[1:3]]
end

let
# Test from_c
default, with_c, without_c = stacktrace(), stacktrace(true), stacktrace(false)
@test default == without_c
@test length(with_c) > length(without_c)
@test !isempty(filter(frame -> frame.from_c, with_c))
@test isempty(filter(frame -> frame.from_c, without_c))

# Test remove_frames!
stack = StackTraces.remove_frames!(grandparent(), :parent)
@test stack[1] == StackFrame(
:grandparent, @__FILE__, line_numbers[3], Symbol(""), -1, false, 0
)

stack = StackTraces.remove_frames!(grandparent(), [:child, :something_nonexistent])
@test stack[1:2] == [
StackFrame(:parent, @__FILE__, line_numbers[2], Symbol(""), -1, false, 0),
StackFrame(:grandparent, @__FILE__, line_numbers[3], Symbol(""), -1, false, 0)
]
end

@test StackTraces.lookup(C_NULL) == StackTraces.UNKNOWN

let
# No errors should mean nothing in catch_backtrace
@test catch_backtrace() == StackFrame[]

@noinline bad_function() = nonexistent_var + 1
@noinline bad_function() = throw(UndefVarError(:nonexistent))
@noinline function try_stacktrace()
try
bad_function()
Expand All @@ -56,16 +66,14 @@ let
return catch_stacktrace()
end
end
line_numbers = @__LINE__ .- [5, 10, 15]
line_numbers = @__LINE__ .- [15, 10, 5]

# Test try...catch with stacktrace
@test try_stacktrace()[1] == StackFrame(
:try_stacktrace, @__FILE__, line_numbers[2], Symbol(""), -1, false, 0
)
@test try_stacktrace()[1] == StackFrame(:try_stacktrace, @__FILE__, line_numbers[2])

# Test try...catch with catch_stacktrace
@test try_catch()[1:2] == [
StackFrame(:bad_function, @__FILE__, line_numbers[1], Symbol(""), -1, false, 0),
StackFrame(:try_catch, @__FILE__, line_numbers[3], Symbol(""), -1, false, 0)
StackFrame(:bad_function, @__FILE__, line_numbers[1]),
StackFrame(:try_catch, @__FILE__, line_numbers[3])
]
end

0 comments on commit 6daf1eb

Please sign in to comment.