Skip to content
This repository has been archived by the owner on Mar 11, 2021. It is now read-only.

Commit

Permalink
Ensure we have at least a printed stack trace when application.Transa…
Browse files Browse the repository at this point in the history
…ction recovers (#2094)
  • Loading branch information
kwk authored and baijum committed May 24, 2018
1 parent 60b9d64 commit e3ab0cf
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
3 changes: 2 additions & 1 deletion application/transaction.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package application

import (
"runtime/debug"
"time"

"github.com/fabric8-services/fabric8-wit/log"
Expand Down Expand Up @@ -35,7 +36,7 @@ func Transactional(db DB, todo func(f Application) error) error {
go func(tx Transaction) {
defer func() {
if err := recover(); err != nil {
errorChan <- errors.Errorf("recovered %v", err)
errorChan <- errors.Errorf("recovered %v. stack: %s", err, debug.Stack())
}
}()
errorChan <- todo(tx)
Expand Down
29 changes: 29 additions & 0 deletions application/transaction_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package application_test

import (
"fmt"
"testing"
"time"

Expand Down Expand Up @@ -54,3 +55,31 @@ func (test *TestTransaction) TestTransactionOut() {
require.Error(test.T(), err)
assert.Contains(test.T(), err.Error(), "database transaction timeout!")
}

func (test *TestTransaction) TestTransactionPanicAndRecoverWithStack() {
// then
err := application.Transactional(test.db, func(appl application.Application) error {
bar := func(a, b interface{}) {
// This comparison while legal at compile time will cause a runtime
// error like this: "comparing uncomparable type
// map[string]interface {}". The transaction will panic and recover
// but you will probably never find out where the error came from if
// the stack is not captured in the transaction recovery. This test
// ensures that the stack is captured.
if a == b {
fmt.Printf("never executed")
}
}
foo := func() {
a := map[string]interface{}{}
b := map[string]interface{}{}
bar(a, b)
}
foo()
return nil
})
// then
require.Error(test.T(), err)
// ensure there's a proper stack trace that contains the name of this test
require.Contains(test.T(), err.Error(), "(*TestTransaction).TestTransactionPanicAndRecoverWithStack.func1(")
}

0 comments on commit e3ab0cf

Please sign in to comment.