Skip to content

Commit

Permalink
Merge pull request #66 from hpidcock/more-hooks
Browse files Browse the repository at this point in the history
#66

Adds two extra hooks for sstxn manipulation for testing.
- Started hook is called after StartTransaction on the mgo.Session.
- Asserted hook is called after transaction assertions have been made.
  • Loading branch information
jujubot authored Jul 29, 2022
2 parents eea05a2 + 8a383f5 commit ff804ce
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/vendor
.vscode/
30 changes: 30 additions & 0 deletions txn.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,32 @@ func (tr *transactionRunner) RunTransaction(transaction *Transaction) error {
}
start := tr.clock.Now()
runner := tr.newRunner()
if len(testHooks) > 0 {
if sstxnRunner, ok := runner.(*sstxn.Runner); ok {
started := testHooks[0].Started
if started != nil {
sstxnRunner.SetStartHook(func() {
logger.Infof("transaction 'started' hook start")
started()
logger.Infof("transaction 'started' hook end")
})
}
asserted := testHooks[0].Asserted
if asserted != nil {
sstxnRunner.SetPostAssertHook(func() {
logger.Infof("transaction 'asserted' hook start")
asserted()
logger.Infof("transaction 'asserted' hook end")
})
}
if started != nil || asserted != nil {
defer func() {
sstxnRunner.SetStartHook(nil)
sstxnRunner.SetPostAssertHook(nil)
}()
}
}
}
err := runner.Run(transaction.Ops, "", nil)
if tr.runTransactionObserver != nil {
transaction.Error = err
Expand All @@ -421,6 +447,10 @@ func (tr *transactionRunner) MaybePruneTransactions(pruneOpts PruneOptions) erro
type TestHook struct {
Before func()
After func()
// Started only works for serverside txns
Started func()
// Asserted only works for serverside txns
Asserted func()
}

// TestHooks returns the test hooks for a transaction runner.
Expand Down
113 changes: 113 additions & 0 deletions txn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,119 @@ func (s *txnSuite) TestBeforeHooks(c *gc.C) {
c.Assert(found, gc.DeepEquals, doc)
}

func (s *sstxnSuite) TestStartedHooks(c *gc.C) {
s.insertDoc(c, "1", "Simple")

secondSession := s.collection.Database.Session.Copy()
defer secondSession.Close()
secondRunner := jujutxn.NewRunner(jujutxn.RunnerParams{
Database: secondSession.DB("juju"),
ChangeLogName: "txns.log",
ServerSideTransactions: true,
PauseFunc: func(dur time.Duration) {
s.backoffs = append(s.backoffs, dur)
},
})

setDocName := func(id, name string) {
ops := []txn.Op{{
C: s.collection.Name,
Id: id,
Assert: txn.DocExists,
Update: bson.D{{"$set", bson.D{{"name", name}}}},
}}
err := secondRunner.RunTransaction(&jujutxn.Transaction{
Ops: ops,
Attempt: 0,
})
c.Assert(err, gc.IsNil)
}

hooks := []jujutxn.TestHook{
{Started: func() { setDocName("1", "FooBar") }},
{Started: func() { setDocName("1", "Foo") }},
}
defer txntesting.SetTestHooks(c, s.txnRunner, hooks...).Check()
maxAttempt := 0
buildTxn := func(attempt int) ([]txn.Op, error) {
maxAttempt = attempt
ops := []txn.Op{{
C: s.collection.Name,
Id: "1",
Assert: bson.D{{"name", "Foo"}},
Update: bson.D{{"$set", bson.D{{"name", "Bar"}}}},
}}
return ops, nil
}
err := s.txnRunner.Run(buildTxn)
c.Assert(err, gc.IsNil)
var found simpleDoc
err = s.collection.FindId("1").One(&found)
c.Assert(err, gc.IsNil)
c.Assert(maxAttempt, gc.Equals, 1)
doc := simpleDoc{"1", "Bar"}
c.Assert(found, gc.DeepEquals, doc)
}

func (s *sstxnSuite) TestAssertedHooks(c *gc.C) {
s.insertDoc(c, "1", "Foo")

secondSession := s.collection.Database.Session.Copy()
defer secondSession.Close()
secondRunner := jujutxn.NewRunner(jujutxn.RunnerParams{
Database: secondSession.DB("juju"),
ChangeLogName: "txns.log",
ServerSideTransactions: true,
PauseFunc: func(dur time.Duration) {
s.backoffs = append(s.backoffs, dur)
},
})

setDocName := func(id, name string) {
ops := []txn.Op{{
C: s.collection.Name,
Id: id,
Assert: txn.DocExists,
Update: bson.D{{"$set", bson.D{{"name", name}}}},
}}
err := secondRunner.RunTransaction(&jujutxn.Transaction{
Ops: ops,
Attempt: 0,
})
c.Assert(err, gc.IsNil)
}

asserted := false
hooks := []jujutxn.TestHook{
{Asserted: func() {
asserted = true
setDocName("1", "FooBar")
}},
{Started: func() { setDocName("1", "Foo") }},
}
defer txntesting.SetTestHooks(c, s.txnRunner, hooks...).Check()
maxAttempt := 0
buildTxn := func(attempt int) ([]txn.Op, error) {
maxAttempt = attempt
ops := []txn.Op{{
C: s.collection.Name,
Id: "1",
Assert: bson.D{{"name", "Foo"}},
Update: bson.D{{"$set", bson.D{{"name", "Bar"}}}},
}}
return ops, nil
}
err := s.txnRunner.Run(buildTxn)
c.Assert(err, gc.IsNil)
c.Assert(asserted, jc.IsTrue)
var found simpleDoc
err = s.collection.FindId("1").One(&found)
c.Assert(err, gc.IsNil)
c.Assert(maxAttempt, gc.Equals, 1)
doc := simpleDoc{"1", "Bar"}
c.Assert(found, gc.DeepEquals, doc)
}

func (s *txnSuite) TestAfterHooks(c *gc.C) {
changeFuncs := []func(){
func() { s.insertDoc(c, "1", "Foo") },
Expand Down

0 comments on commit ff804ce

Please sign in to comment.