Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: do not print backtrace for TestSetExceptions and Pkg.test() exception. #19750

Merged
merged 1 commit into from
Jan 6, 2017

Conversation

KristofferC
Copy link
Member

@KristofferC KristofferC commented Dec 29, 2016

Removes the backtraces that points to internal functions that are running tests when these test runners run as expected.

Difference between master and PR

PR:

image

Master

image

@tkelman
Copy link
Contributor

tkelman commented Dec 29, 2016

Wouldn't it be cleaner to use dispatch on exception type to ignore the backtrace keyword argument for some types? That you could even do in your juliarc, probably.

@KristofferC
Copy link
Member Author

KristofferC commented Dec 29, 2016

Do you mean to add something like

Base.showerror(io::IO, ex::TestSetException, bt) = Base.showerror(io, ex)

?

I don't see why .juliarc.jl is relevant.

@kshyatt kshyatt added error handling Handling of exceptions by Julia or the user testsystem The unit testing framework and Test stdlib labels Dec 29, 2016
@KristofferC
Copy link
Member Author

AV seemingly got stuck: https://gist.github.com/KristofferC/33b0f4544ec790e2f8e11a2adcfeaf8a. Close and repoen to restart tests.

@KristofferC KristofferC reopened this Dec 30, 2016
@KristofferC KristofferC changed the title RFC: do not print backtrace for TestSetExceptions RFC: do not print backtrace for TestSetExceptions and Pkg.test() exception. Dec 30, 2016
@KristofferC KristofferC force-pushed the kc/testset_bt_noprint branch 3 times, most recently from c1e0125 to bc0da73 Compare December 30, 2016 14:54

let
io = IOBuffer()
Base.showerror(io, Test.TestSetException(1,2,3,4,Vector{Union{Base.Test.Error, Base.Test.Fail}}()), backtrace())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line wrap

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unaddressed

@tkelman
Copy link
Contributor

tkelman commented Dec 30, 2016

In the case of Pkg.test, I think a verbose keyword argument to control this would be better than suppressing it unconditionally. Otherwise it's hard to trace and debug what Pkg.test actually runs.

@KristofferC
Copy link
Member Author

The full command that Pkg.test runs is still printed. Only the back trace to some arbitrary location in Pkg.Entry is suppressed.

@KristofferC
Copy link
Member Author

KristofferC commented Dec 30, 2016

Explicitly, this is still printed:

===============================[ ERROR: Testpkg ]===============================

failed process: Process(`/home/kristoffer/Downloads/julia-3c9d75391c/bin/julia -Cx86-64 -J/home/kristoffer/Downloads/julia-3c9d75391c/lib/julia/sys.so --compile=yes --depwarn=yes --check-bounds=yes --code-coverage=none --color=yes --compilecache=yes /home/kristoffer/.julia/v0.5/Testpkg/test/runtests.jl`, ProcessExited(1)) [1]

================================================================================

What information do you want from the backtrace I removed?

@KristofferC
Copy link
Member Author

Any objections against this?

@tkelman
Copy link
Contributor

tkelman commented Dec 31, 2016

What information do you want from the backtrace I removed?

The ability to see not just what Pkg.Test runs, but how it gets there. Maybe not shown by default, but make it possible.

@KristofferC
Copy link
Member Author

The fact that an exception is thrown is basically a hack so that the process will exit with non zero status if run in noninteractive mode and being able to catch the exception when running in the REPL. To see how arbitrary function gets called, isn't that what you use debuggers for. My point is that, if a PkgTestException is thrown, it means that Pkg.test() works exactly as it should and just as with any other function that does what it should, we don't randomly print a backtrace for it. If Pkg.test() actually errors for some other reason, then its backtrace will be printed.

@tkelman
Copy link
Contributor

tkelman commented Dec 31, 2016

Most functions don't throw exceptions in the course of doing what they should - or they intentionally catch them. If throwing an exception is a hack, then suppressing the backtrace just for this specific type of exception is putting yet more hacks on top of it.

@KristofferC
Copy link
Member Author

Yes. And it gives a significant boost to user experience. I'm not sure I got your point.

@KristofferC
Copy link
Member Author

Consider the case where Pkg.test() is always run in a separate process. The throw in the current code would then instead have been exit(1) and would then not print a backtrace. The current backtrace being printed is hence just an artifact of the implementation detail that Pkg.test() is run in the current process and it would be a bad user experience to exit that process. This PR removes that artifact.

@tkelman
Copy link
Contributor

tkelman commented Dec 31, 2016

The backtrace is an artifact of using an exception, and our normal handling of exceptions. If you're not treating it the way we treat normal exceptions, because you're arguing that it's not exceptional behavior but expected, then it's control flow. At that point it seems like you mostly want to print a message in red and could return the results instead.

@KristofferC
Copy link
Member Author

It is "exit status"-control flow. Doing what you suggest would exit the process with the wrong exit code when Pkg.test() gets run in non interactive mode.

@stevengj
Copy link
Member

What if a test fails not due to @test <false> but rather due to the test throwing an exception?

@KristofferC
Copy link
Member Author

There are three backtraces currently being printed when Pkg.test fails. The one you are concerned about is the first one and that one is not touched in the PR. There is another PR dealing with that one #19751.

@KristofferC
Copy link
Member Author

Good to go?

@tkelman
Copy link
Contributor

tkelman commented Jan 2, 2017

I still don't like the unconditional hiding of information here.

@KristofferC
Copy link
Member Author

KristofferC commented Jan 2, 2017

You are using the word "information" but what is removed here is not any actionable information. It is purely implementation details that accidentally leak to the user during completely normal operation of a function. In fact, for every function that we don't print a backtrace to during normal operations we are "hiding information". And that is a crucial part of delivering a good user experience (which the current one is definitely not).

If someone says they want to see the backtrace to where sin is called, the answer would be to set a breakpoint and print the backtrace in a debugger. We wouldn't add a sin(x; backtrace=false) function, which is what it feels like you are proposing.

Seems we are at an impasse so opinions from more people would be good to hear.

@tkelman
Copy link
Contributor

tkelman commented Jan 2, 2017

Package tests failing arguably aren't normal operation - there was a failure, and it's worth displaying how and where it happened.

@KristofferC
Copy link
Member Author

KristofferC commented Jan 2, 2017

it's worth displaying how and where it happened.

This is not being touched in this PR. The full command to the process running the tests together with the backtrace in that process is printed.

@KristofferC
Copy link
Member Author

If a plumber comes to your house and says that a pipe is broken, would you really ask him about the color of his underwear?

@quinnj
Copy link
Member

quinnj commented Jan 2, 2017

I completely agree with @KristofferC here and this change is a significant improvement. I think we just have to view Pkg.test for what it does: it's running the tests for a package; if those tests fail, what's helpful is a message about what failed and where (in the package itself). In my mind, Pkg.test itself isn't and shouldn't be the thing "failing" here, so we shouldn't see it's backtrace; it DID it's job just by TRYING to run the tests. In my mind, this is the exact purpose for having a try-catch block in the language; you desire some alternate behavior to throwing in the case the tryed code has an error.

@tkelman
Copy link
Contributor

tkelman commented Jan 2, 2017

In my mind, this is the exact purpose for having a try-catch block in the language; you desire some alternate behavior to throwing in the case the tryed code has an error.

This isn't a try-catch though, it's not alternate behavior. It's throwing an exception but always hiding its particular backtrace because we apparently don't like this piece of information? The thing that caused the exit code to be as desired was an error thrown from inside Pkg.

@KristofferC
Copy link
Member Author

KristofferC commented Jan 2, 2017

How about changing

throw(PkgTestError(join(messages, "and")))

to something like

print_with_color(Base.error_color(), STDOUT, join(messages, "and"))
!Base.isinteractive() && exit(1)

@StefanKarpinski
Copy link
Member

Is exit(1) ok in this situation because this is being run in a subprocess?

@KristofferC
Copy link
Member Author

I am not sure, haven't tried it yet. Just trying to make progress.

@StefanKarpinski StefanKarpinski added this to the 0.6.0 milestone Jan 2, 2017
@KristofferC KristofferC force-pushed the kc/testset_bt_noprint branch from 57359b6 to 5b5a226 Compare January 2, 2017 18:52
@KristofferC
Copy link
Member Author

I implemented my last comment and just stop throwing an exception. Worked as expected and gave the wrong exit status for everything I tried it on. @tkelman is this better now since it doesn't "pun" on exception throwing?

showerror(io, er, bt)
println(io)
end
Base.showerror(IOContext(STDERR, :limit => true), er, bt)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was left out from #19569

@tkelman
Copy link
Contributor

tkelman commented Jan 2, 2017

Wouldn't that make Pkg.test in a script un-catchable if it fails? My preference would be for a verbose flag to Pkg.test where you could turn the backtrace back on if you wanted it.

@KristofferC
Copy link
Member Author

Removed last commit since being able to catch a failing Pkg.test seems useful. I can't justify adding extra maintenance cost in terms of documentation and code for something that I feel no one will ever use and does not provide relevant information.

@StefanKarpinski
Copy link
Member

I think we should go ahead with this. If we find that there are situations where we actually miss the omitted information, then we can add an option to show it again.

tkelman
tkelman previously requested changes Jan 3, 2017
@@ -396,6 +396,12 @@ end
@test_throws ErrorException @testset "$(error())" begin
end

let
io = IOBuffer()
Base.showerror(io, Test.TestSetException(1,2,3,4,Vector{Union{Base.Test.Error, Base.Test.Fail}}()), backtrace())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrap long lines

@KristofferC KristofferC force-pushed the kc/testset_bt_noprint branch 2 times, most recently from 61adfd7 to 2bf98f7 Compare January 3, 2017 22:29
@KristofferC KristofferC force-pushed the kc/testset_bt_noprint branch from 2bf98f7 to fce015b Compare January 3, 2017 22:57
@KristofferC
Copy link
Member Author

KristofferC commented Jan 3, 2017

Squashed, fixed some of the colors and updated first post with screenshot comparisons to make it more clear what is being changed.

@musm
Copy link
Contributor

musm commented Jan 3, 2017

@KristofferC why is the macro expansion stuff useful to print in the stack trace as well?

@KristofferC
Copy link
Member Author

KristofferC commented Jan 3, 2017

Not all of them are (the first one shows where the test is executed). The other ones are in the same stackframe because of inlining so not sure how to deal with it.

@tkelman tkelman dismissed their stale review January 4, 2017 09:26

style fixed

@StefanKarpinski
Copy link
Member

Appears to not just be the 32-bit failure we've been seeing.

@StefanKarpinski
Copy link
Member

Now the only failure is the ongoing 32-bit Linux failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
error handling Handling of exceptions by Julia or the user testsystem The unit testing framework and Test stdlib
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants