@@ -703,6 +703,8 @@ func (s *S) TestPurgeMissingPipelineSizeLimit(c *C) {
703703}
704704
705705var flaky = flag .Bool ("flaky" , false , "Include flaky tests" )
706+ var txnQueueLength = flag .Int ("qlength" , 100 , "txn-queue length for tests" )
707+
706708
707709func (s * S ) TestTxnQueueStressTest (c * C ) {
708710 // This fails about 20% of the time on Mongo 3.2 (I haven't tried
@@ -776,3 +778,117 @@ func (s *S) TestTxnQueueStressTest(c *C) {
776778 }
777779 }
778780}
781+
782+ type txnQueue struct {
783+ Queue []string `bson:"txn-queue"`
784+ }
785+
786+ func (s * S ) TestTxnQueueAssertionGrowth (c * C ) {
787+ txn .SetDebug (false ) // too much spam
788+ err := s .accounts .Insert (M {"_id" : 0 , "balance" : 0 })
789+ c .Assert (err , IsNil )
790+ // Create many assertion only transactions.
791+ t := time .Now ()
792+ ops := []txn.Op {{
793+ C : "accounts" ,
794+ Id : 0 ,
795+ Assert : M {"balance" : 0 },
796+ }}
797+ for n := 0 ; n < * txnQueueLength ; n ++ {
798+ err = s .runner .Run (ops , "" , nil )
799+ c .Assert (err , IsNil )
800+ }
801+ var qdoc txnQueue
802+ err = s .accounts .FindId (0 ).One (& qdoc )
803+ c .Assert (err , IsNil )
804+ c .Check (len (qdoc .Queue ), Equals , * txnQueueLength )
805+ c .Logf ("%8.3fs to set up %d assertions" , time .Since (t ).Seconds (), * txnQueueLength )
806+ t = time .Now ()
807+ txn .SetChaos (txn.Chaos {})
808+ ops = []txn.Op {{
809+ C : "accounts" ,
810+ Id : 0 ,
811+ Update : M {"$inc" : M {"balance" : 100 }},
812+ }}
813+ err = s .runner .Run (ops , "" , nil )
814+ c .Logf ("%8.3fs to clear N=%d assertions and add one more txn" ,
815+ time .Since (t ).Seconds (), * txnQueueLength )
816+ err = s .accounts .FindId (0 ).One (& qdoc )
817+ c .Assert (err , IsNil )
818+ c .Check (len (qdoc .Queue ), Equals , 1 )
819+ }
820+
821+ func (s * S ) TestTxnQueueBrokenPrepared (c * C ) {
822+ txn .SetDebug (false ) // too much spam
823+ badTxnToken := "123456789012345678901234_deadbeef"
824+ err := s .accounts .Insert (M {"_id" : 0 , "balance" : 0 , "txn-queue" : []string {badTxnToken }})
825+ c .Assert (err , IsNil )
826+ t := time .Now ()
827+ ops := []txn.Op {{
828+ C : "accounts" ,
829+ Id : 0 ,
830+ Update : M {"$set" : M {"balance" : 0 }},
831+ }}
832+ errString := `cannot find transaction ObjectIdHex("123456789012345678901234")`
833+ for n := 0 ; n < * txnQueueLength ; n ++ {
834+ err = s .runner .Run (ops , "" , nil )
835+ c .Assert (err .Error (), Equals , errString )
836+ }
837+ var qdoc txnQueue
838+ err = s .accounts .FindId (0 ).One (& qdoc )
839+ c .Assert (err , IsNil )
840+ c .Check (len (qdoc .Queue ), Equals , * txnQueueLength + 1 )
841+ c .Logf ("%8.3fs to set up %d 'prepared' txns" , time .Since (t ).Seconds (), * txnQueueLength )
842+ t = time .Now ()
843+ s .accounts .UpdateId (0 , bson.M {"$pullAll" : bson.M {"txn-queue" : []string {badTxnToken }}})
844+ ops = []txn.Op {{
845+ C : "accounts" ,
846+ Id : 0 ,
847+ Update : M {"$inc" : M {"balance" : 100 }},
848+ }}
849+ err = s .runner .ResumeAll ()
850+ c .Assert (err , IsNil )
851+ c .Logf ("%8.3fs to ResumeAll N=%d 'prepared' txns" ,
852+ time .Since (t ).Seconds (), * txnQueueLength )
853+ err = s .accounts .FindId (0 ).One (& qdoc )
854+ c .Assert (err , IsNil )
855+ c .Check (len (qdoc .Queue ), Equals , 1 )
856+ }
857+
858+ func (s * S ) TestTxnQueuePreparing (c * C ) {
859+ txn .SetDebug (false ) // too much spam
860+ err := s .accounts .Insert (M {"_id" : 0 , "balance" : 0 , "txn-queue" : []string {}})
861+ c .Assert (err , IsNil )
862+ t := time .Now ()
863+ txn .SetChaos (txn.Chaos {
864+ KillChance : 1.0 ,
865+ Breakpoint : "set-prepared" ,
866+ })
867+ ops := []txn.Op {{
868+ C : "accounts" ,
869+ Id : 0 ,
870+ Update : M {"$set" : M {"balance" : 0 }},
871+ }}
872+ for n := 0 ; n < * txnQueueLength ; n ++ {
873+ err = s .runner .Run (ops , "" , nil )
874+ c .Assert (err , Equals , txn .ErrChaos )
875+ }
876+ var qdoc txnQueue
877+ err = s .accounts .FindId (0 ).One (& qdoc )
878+ c .Assert (err , IsNil )
879+ c .Check (len (qdoc .Queue ), Equals , * txnQueueLength )
880+ c .Logf ("%8.3fs to set up %d 'preparing' txns" , time .Since (t ).Seconds (), * txnQueueLength )
881+ txn .SetChaos (txn.Chaos {})
882+ t = time .Now ()
883+ err = s .runner .ResumeAll ()
884+ c .Logf ("%8.3fs to ResumeAll N=%d 'preparing' txns" ,
885+ time .Since (t ).Seconds (), * txnQueueLength )
886+ err = s .accounts .FindId (0 ).One (& qdoc )
887+ c .Assert (err , IsNil )
888+ expectedCount := 100
889+ if * txnQueueLength <= expectedCount {
890+ expectedCount = * txnQueueLength - 1
891+ }
892+ c .Check (len (qdoc .Queue ), Equals , expectedCount )
893+ }
894+
0 commit comments