1717package com .mongodb .client .unified ;
1818
1919import com .mongodb .assertions .Assertions ;
20+ import org .opentest4j .AssertionFailedError ;
2021
2122import java .util .ArrayList ;
2223import java .util .Arrays ;
2324import java .util .List ;
25+ import java .util .function .Function ;
2426import java .util .function .Supplier ;
2527
2628import static com .mongodb .ClusterFixture .isDataLakeTest ;
2729import static com .mongodb .ClusterFixture .isDiscoverableReplicaSet ;
2830import static com .mongodb .ClusterFixture .isServerlessTest ;
2931import static com .mongodb .ClusterFixture .isSharded ;
3032import static com .mongodb .ClusterFixture .serverVersionLessThan ;
31- import static com .mongodb .client .unified .UnifiedTestModifications .Modifier .FORCE_FLAKY ;
3233import static com .mongodb .assertions .Assertions .assertNotNull ;
3334import static com .mongodb .client .unified .UnifiedTestModifications .Modifier .IGNORE_EXTRA_EVENTS ;
35+ import static com .mongodb .client .unified .UnifiedTestModifications .Modifier .RETRY ;
3436import static com .mongodb .client .unified .UnifiedTestModifications .Modifier .SKIP ;
3537import static com .mongodb .client .unified .UnifiedTestModifications .Modifier .SLEEP_AFTER_CURSOR_CLOSE ;
3638import static com .mongodb .client .unified .UnifiedTestModifications .Modifier .SLEEP_AFTER_CURSOR_OPEN ;
3739import static com .mongodb .client .unified .UnifiedTestModifications .Modifier .WAIT_FOR_BATCH_CURSOR_CREATION ;
3840
3941public final class UnifiedTestModifications {
40- public static void doSkips (final TestDef def ) {
42+ public static void applyCustomizations (final TestDef def ) {
4143
4244 // TODO reasons for retry
43- def .modify (FORCE_FLAKY )
44- // Exception in encryption library: ChangeCipherSpec message sequence violation
45- .test ("client-side-encryption" , "namedKMS-createDataKey" , "create datakey with named KMIP KMS provider" )
46- // Number of checked out connections must match expected
47- .test ("load-balancers" , "cursors are correctly pinned to connections for load-balanced clusters" , "pinned connections are returned after a network error during a killCursors request" )
45+ // Exception in encryption library: ChangeCipherSpec message sequence violation
46+ def .retry ("TODO reason" )
47+ .whenExceptionContains ("ChangeCipherSpec message sequence violation" )
48+ .test ("client-side-encryption" , "namedKMS-createDataKey" , "create datakey with named KMIP KMS provider" );
49+
50+ def .retry ("TODO reason" )
51+ .whenExceptionContains ("Number of checked out connections must match expected" )
52+ .test ("load-balancers" , "cursors are correctly pinned to connections for load-balanced clusters" , "pinned connections are returned after a network error during a killCursors request" );
53+
54+ def .retry ("TODO reason" )
4855 .test ("client-side-encryption" , "namedKMS-rewrapManyDataKey" , "rewrap to kmip:name1" );
4956
5057 // atlas-data-lake
@@ -288,6 +295,7 @@ public static final class TestDef {
288295 private final boolean reactive ;
289296
290297 private final List <Modifier > modifiers = new ArrayList <>();
298+ private Function <AssertionFailedError , Boolean > matchesError ;
291299
292300 private TestDef (final String dir , final String file , final String test , final boolean reactive ) {
293301 this .dir = dir ;
@@ -332,7 +340,8 @@ public TestApplicator skipNoncompliant(final String reason) {
332340 * @param reason reason for skipping the test
333341 */
334342 public TestApplicator skipNoncompliantReactive (final String reason ) {
335- return new TestApplicator (this , reason , SKIP );
343+ return new TestApplicator (this , reason , SKIP )
344+ .when (() -> isReactive ());
336345 }
337346
338347 /**
@@ -350,6 +359,14 @@ public TestApplicator skipUnknownReason(final String reason) {
350359 return new TestApplicator (this , reason , SKIP );
351360 }
352361
362+
363+ /**
364+ * The test will be retried, for the reason provided
365+ */
366+ public TestApplicator retry (final String reason ) {
367+ return new TestApplicator (this , reason , RETRY );
368+ }
369+
353370 public TestApplicator modify (final Modifier ... modifiers ) {
354371 return new TestApplicator (this , null , modifiers );
355372 }
@@ -361,24 +378,33 @@ public boolean isReactive() {
361378 public boolean wasAssignedModifier (final Modifier modifier ) {
362379 return this .modifiers .contains (modifier );
363380 }
381+
382+ public boolean matchesError (final AssertionFailedError e ) {
383+ if (matchesError != null ) {
384+ return matchesError .apply (e );
385+ }
386+ return false ;
387+ }
364388 }
365389
366390 /**
367391 * Applies settings to the underlying test definition. Chainable.
368392 */
369393 public static final class TestApplicator {
370394 private final TestDef testDef ;
371- private final List <Modifier > modifiersToApply ;
372395 private Supplier <Boolean > precondition ;
373396 private boolean matchWasPerformed = false ;
374397
398+ private final List <Modifier > modifiersToApply ;
399+ private Function <AssertionFailedError , Boolean > matchesError ;
400+
375401 private TestApplicator (
376402 final TestDef testDef ,
377403 final String reason ,
378404 final Modifier ... modifiersToApply ) {
379405 this .testDef = testDef ;
380406 this .modifiersToApply = Arrays .asList (modifiersToApply );
381- if (this .modifiersToApply .contains (SKIP )) {
407+ if (this .modifiersToApply .contains (SKIP ) || this . modifiersToApply . contains ( RETRY ) ) {
382408 assertNotNull (reason );
383409 }
384410 }
@@ -390,6 +416,7 @@ private TestApplicator onMatch(final boolean match) {
390416 }
391417 if (match ) {
392418 this .testDef .modifiers .addAll (this .modifiersToApply );
419+ this .testDef .matchesError = this .matchesError ;
393420 }
394421 return this ;
395422 }
@@ -481,6 +508,13 @@ public TestApplicator when(final Supplier<Boolean> precondition) {
481508 this .precondition = precondition ;
482509 return this ;
483510 }
511+
512+ public TestApplicator whenExceptionContains (final String fragment ) {
513+ this .matchesError = (final AssertionFailedError e ) -> {
514+ return e .getCause ().getMessage ().contains (fragment );
515+ };
516+ return this ;
517+ }
484518 }
485519
486520 public enum Modifier {
0 commit comments