3737import com .mongodb .connection .SocketSettings ;
3838import com .mongodb .connection .SslSettings ;
3939import com .mongodb .event .CommandEvent ;
40+ import com .mongodb .event .CommandStartedEvent ;
4041import com .mongodb .internal .connection .TestCommandListener ;
4142import com .mongodb .lang .Nullable ;
4243import org .bson .BsonArray ;
5253import org .junit .Test ;
5354import org .junit .runner .RunWith ;
5455import org .junit .runners .Parameterized ;
55- import util .JsonPoweredTestHelper ;
5656
57- import java .io .File ;
58- import java .io .IOException ;
59- import java .net .URISyntaxException ;
6057import java .util .ArrayList ;
61- import java .util .Collection ;
6258import java .util .HashMap ;
6359import java .util .List ;
6460import java .util .Map ;
6561import java .util .concurrent .TimeUnit ;
6662
6763import static com .mongodb .ClusterFixture .getMultiMongosConnectionString ;
68- import static com .mongodb .JsonTestServerVersionChecker .skipTest ;
6964import static com .mongodb .async .client .Fixture .getConnectionString ;
7065import static com .mongodb .async .client .Fixture .getDefaultDatabaseName ;
7166import static com .mongodb .async .client .Fixture .isSharded ;
7570import static java .util .concurrent .TimeUnit .MILLISECONDS ;
7671import static org .junit .Assert .assertEquals ;
7772import static org .junit .Assert .assertFalse ;
73+ import static org .junit .Assert .assertNotEquals ;
7874import static org .junit .Assert .assertNotNull ;
7975import static org .junit .Assert .assertNull ;
8076import static org .junit .Assert .assertTrue ;
8480
8581// See https://github.com/mongodb/specifications/tree/master/source/transactions/tests
8682@ RunWith (Parameterized .class )
87- public class TransactionsTest {
83+ public abstract class AbstractUnifiedTest {
8884
8985 private final String filename ;
9086 private final String description ;
@@ -104,8 +100,8 @@ public class TransactionsTest {
104100
105101 private static final long MIN_HEARTBEAT_FREQUENCY_MS = 50L ;
106102
107- public TransactionsTest (final String filename , final String description , final BsonArray data , final BsonDocument definition ,
108- final boolean skipTest ) {
103+ public AbstractUnifiedTest (final String filename , final String description , final BsonArray data , final BsonDocument definition ,
104+ final boolean skipTest ) {
109105 this .filename = filename ;
110106 this .description = description ;
111107 this .databaseName = getDefaultDatabaseName ();
@@ -353,7 +349,7 @@ private void executeOperations(final BsonArray operations, final boolean throwEx
353349 BsonValue expectedResult = operation .get ("result" );
354350 String receiver = operation .getString ("object" ).getValue ();
355351 final ClientSession clientSession = receiver .startsWith ("session" ) ? sessionsMap .get (receiver )
356- : (operation .getDocument ("arguments" ).containsKey ("session" )
352+ : (operation .getDocument ("arguments" , new BsonDocument () ).containsKey ("session" )
357353 ? sessionsMap .get (operation .getDocument ("arguments" ).getString ("session" ).getValue ()) : null );
358354 try {
359355 if (operationName .equals ("startTransaction" )) {
@@ -401,13 +397,31 @@ public void execute() {
401397 } else {
402398 assertFalse (session .hasActiveTransaction ());
403399 }
400+ } else if (operationName .equals ("endSession" )) {
401+ clientSession .close ();
404402 } else if (operation .getBoolean ("error" , BsonBoolean .FALSE ).getValue ()) {
405403 try {
406404 helper .getOperationResults (operation , clientSession );
407405 fail ("Error expected but none thrown" );
408406 } catch (Exception e ) {
409407 // Expected failure ignore
410408 }
409+ } else if (operationName .equals ("assertDifferentLsidOnLastTwoCommands" )) {
410+ List <CommandEvent > events = lastTwoCommandEvents ();
411+ assertNotEquals (((CommandStartedEvent ) events .get (0 )).getCommand ().getDocument ("lsid" ),
412+ ((CommandStartedEvent ) events .get (1 )).getCommand ().getDocument ("lsid" ));
413+ } else if (operationName .equals ("assertSameLsidOnLastTwoCommands" )) {
414+ List <CommandEvent > events = lastTwoCommandEvents ();
415+ assertEquals (((CommandStartedEvent ) events .get (0 )).getCommand ().getDocument ("lsid" ),
416+ ((CommandStartedEvent ) events .get (1 )).getCommand ().getDocument ("lsid" ));
417+ } else if (operationName .equals ("assertSessionDirty" )) {
418+ assertNotNull (clientSession );
419+ assertNotNull (clientSession .getServerSession ());
420+ assertTrue (clientSession .getServerSession ().isMarkedDirty ());
421+ } else if (operationName .equals ("assertSessionNotDirty" )) {
422+ assertNotNull (clientSession );
423+ assertNotNull (clientSession .getServerSession ());
424+ assertFalse (clientSession .getServerSession ().isMarkedDirty ());
411425 } else {
412426 BsonDocument actualOutcome = helper .getOperationResults (operation , clientSession );
413427 if (expectedResult != null ) {
@@ -426,46 +440,7 @@ public void execute() {
426440 assertFalse (String .format ("Expected error code '%s' but none thrown for operation %s" ,
427441 getErrorCodeNameField (expectedResult ), operationName ), hasErrorCodeNameField (expectedResult ));
428442 } catch (RuntimeException e ) {
429- boolean passedAssertion = false ;
430- if (hasErrorLabelsContainField (expectedResult )) {
431- if (e instanceof MongoException ) {
432- MongoException mongoException = (MongoException ) e ;
433- for (String curErrorLabel : getErrorLabelsContainField (expectedResult )) {
434- assertTrue (String .format ("Expected error label '%s but found labels '%s' for operation %s" ,
435- curErrorLabel , mongoException .getErrorLabels (), operationName ),
436- mongoException .hasErrorLabel (curErrorLabel ));
437- }
438- passedAssertion = true ;
439- }
440- }
441- if (hasErrorLabelsOmitField (expectedResult )) {
442- if (e instanceof MongoException ) {
443- MongoException mongoException = (MongoException ) e ;
444- for (String curErrorLabel : getErrorLabelsOmitField (expectedResult )) {
445- assertFalse (String .format ("Expected error label '%s omitted but found labels '%s' for operation %s" ,
446- curErrorLabel , mongoException .getErrorLabels (), operationName ),
447- mongoException .hasErrorLabel (curErrorLabel ));
448- }
449- passedAssertion = true ;
450- }
451- }
452- if (hasErrorContainsField (expectedResult )) {
453- String expectedError = getErrorContainsField (expectedResult );
454- assertTrue (String .format ("Expected '%s' but got '%s' for operation %s" , expectedError , e .getMessage (),
455- operationName ), e .getMessage ().toLowerCase ().contains (expectedError .toLowerCase ()));
456- passedAssertion = true ;
457- }
458- if (hasErrorCodeNameField (expectedResult )) {
459- String expectedErrorCodeName = getErrorCodeNameField (expectedResult );
460- if (e instanceof MongoCommandException ) {
461- assertEquals (expectedErrorCodeName , ((MongoCommandException ) e ).getErrorCodeName ());
462- passedAssertion = true ;
463- } else if (e instanceof MongoWriteConcernException ) {
464- assertEquals (expectedErrorCodeName , ((MongoWriteConcernException ) e ).getWriteConcernError ().getCodeName ());
465- passedAssertion = true ;
466- }
467- }
468- if (!passedAssertion || throwExceptions ) {
443+ if (!assertExceptionState (e , expectedResult , operationName ) || throwExceptions ) {
469444 throw e ;
470445 }
471446 }
@@ -477,6 +452,55 @@ public void execute() {
477452 }
478453 }
479454
455+ private boolean assertExceptionState (final RuntimeException e , final BsonValue expectedResult , final String operationName ) {
456+ boolean passedAssertion = false ;
457+ if (hasErrorLabelsContainField (expectedResult )) {
458+ if (e instanceof MongoException ) {
459+ MongoException mongoException = (MongoException ) e ;
460+ for (String curErrorLabel : getErrorLabelsContainField (expectedResult )) {
461+ assertTrue (String .format ("Expected error label '%s but found labels '%s' for operation %s" ,
462+ curErrorLabel , mongoException .getErrorLabels (), operationName ),
463+ mongoException .hasErrorLabel (curErrorLabel ));
464+ }
465+ passedAssertion = true ;
466+ }
467+ }
468+ if (hasErrorLabelsOmitField (expectedResult )) {
469+ if (e instanceof MongoException ) {
470+ MongoException mongoException = (MongoException ) e ;
471+ for (String curErrorLabel : getErrorLabelsOmitField (expectedResult )) {
472+ assertFalse (String .format ("Expected error label '%s omitted but found labels '%s' for operation %s" ,
473+ curErrorLabel , mongoException .getErrorLabels (), operationName ),
474+ mongoException .hasErrorLabel (curErrorLabel ));
475+ }
476+ passedAssertion = true ;
477+ }
478+ }
479+ if (hasErrorContainsField (expectedResult )) {
480+ String expectedError = getErrorContainsField (expectedResult );
481+ assertTrue (String .format ("Expected '%s' but got '%s' for operation %s" , expectedError , e .getMessage (),
482+ operationName ), e .getMessage ().toLowerCase ().contains (expectedError .toLowerCase ()));
483+ passedAssertion = true ;
484+ }
485+ if (hasErrorCodeNameField (expectedResult )) {
486+ String expectedErrorCodeName = getErrorCodeNameField (expectedResult );
487+ if (e instanceof MongoCommandException ) {
488+ assertEquals (expectedErrorCodeName , ((MongoCommandException ) e ).getErrorCodeName ());
489+ passedAssertion = true ;
490+ } else if (e instanceof MongoWriteConcernException ) {
491+ assertEquals (expectedErrorCodeName , ((MongoWriteConcernException ) e ).getWriteConcernError ().getCodeName ());
492+ passedAssertion = true ;
493+ }
494+ }
495+ return passedAssertion ;
496+ }
497+
498+ private List <CommandEvent > lastTwoCommandEvents () {
499+ List <CommandEvent > events = commandListener .getCommandStartedEvents ();
500+ assertTrue (events .size () >= 2 );
501+ return events .subList (events .size () - 2 , events .size ());
502+ }
503+
480504 private TransactionOptions createTransactionOptions (final BsonDocument options ) {
481505 TransactionOptions .Builder builder = TransactionOptions .builder ();
482506 if (options .containsKey ("writeConcern" )) {
@@ -554,19 +578,6 @@ private ClientSession nonNullClientSession(@Nullable final ClientSession clientS
554578 return clientSession ;
555579 }
556580
557- @ Parameterized .Parameters (name = "{0}: {1}" )
558- public static Collection <Object []> data () throws URISyntaxException , IOException {
559- List <Object []> data = new ArrayList <Object []>();
560- for (File file : JsonPoweredTestHelper .getTestFiles ("/transactions" )) {
561- BsonDocument testDocument = JsonPoweredTestHelper .getTestDocument (file );
562- for (BsonValue test : testDocument .getArray ("tests" )) {
563- data .add (new Object []{file .getName (), test .asDocument ().getString ("description" ).getValue (),
564- testDocument .getArray ("data" ), test .asDocument (), skipTest (testDocument , test .asDocument ())});
565- }
566- }
567- return data ;
568- }
569-
570581 private class TargetedFailPoint {
571582 private final BsonDocument failPointDocument ;
572583 private final MongoDatabase adminDB ;
0 commit comments