improve post-hook behavior

We want to be able to register hooks which do cleanup, which may be
registered after the auditor cleanup check, which means that we
want LIFO order for post-hook cleanups.

We also want the test hook cleanup to be deferred, rather than
merely run after the tests are executed. Also, we have to extract
the result from running the test, then execute deferred things,
*then* call os.Exit, because os.Exit bypasses defers.
This commit is contained in:
Seebs 2022-07-21 17:52:58 -05:00 committed by Christopher Lowenthal
parent 8ec5bc5629
commit bfea70d5e4

View file

@ -24,6 +24,10 @@ func RegisterPostTestHook(fn Callback) {
mu.Lock()
defer mu.Unlock()
postHooks = append(postHooks, fn)
// ... but put it at the beginning of the list, so they're LIFO,
// so test hook pairs nest cleanly.
copy(postHooks[1:], postHooks)
postHooks[0] = fn
}
// RegisterPreTestHook registers a function to be called after tests
@ -54,16 +58,27 @@ func RunTestsWithHooks(m *testing.M) {
fmt.Fprint(os.Stderr, "pre-hooks failed, aborting.\n")
os.Exit(ret)
}
ret = m.Run()
mu.Lock()
defer mu.Unlock()
for _, fn := range postHooks {
err := fn()
if err != nil {
fmt.Fprintf(os.Stderr, "post-hook failure: %v\n", err)
ret = 1
}
}
// This inner function lets us get a deferred run of our post-test
// hooks which necessarily succeeds, but can trap an error even
// from those and set the return value. You can't do this with a
// direct os.Exit() wrapper because defers don't run after os.Exit.
// Don't ask how many tries it took me to figure that out, I'll
// just cry.
func() {
defer func() {
mu.Lock()
defer mu.Unlock()
for _, fn := range postHooks {
err := fn()
if err != nil {
fmt.Fprintf(os.Stderr, "post-hook failure: %v\n", err)
ret = 1
}
}
}()
ret = m.Run()
}()
os.Exit(ret)
}