66import java .lang .reflect .Modifier ;
77import java .lang .reflect .Parameter ;
88import java .util .*;
9- import javax .annotation .Nullable ;
109import org .testng .DataProviderHolder ;
1110import org .testng .IDataProviderInterceptor ;
1211import org .testng .IDataProviderListener ;
1312import org .testng .IDataProviderMethod ;
13+ import org .testng .IRetryDataProvider ;
1414import org .testng .ITestClass ;
1515import org .testng .ITestContext ;
1616import org .testng .ITestNGMethod ;
@@ -147,7 +147,7 @@ public static Object[] createConfigurationParameters(
147147 Method m ,
148148 Map <String , String > params ,
149149 Object [] parameterValues ,
150- @ Nullable ITestNGMethod currentTestMethod ,
150+ ITestNGMethod currentTestMethod ,
151151 IAnnotationFinder finder ,
152152 XmlSuite xmlSuite ,
153153 ITestContext ctx ,
@@ -618,34 +618,33 @@ private static IDataProviderMethod findDataProvider(
618618
619619 for (Method m : ClassHelper .getAvailableMethods (cls )) {
620620 IDataProviderAnnotation dp = finder .findAnnotation (m , IDataProviderAnnotation .class );
621- if (null != dp && name .equals (getDataProviderName (dp , m ))) {
622- Object instanceToUse ;
623- if (shouldBeStatic && (m .getModifiers () & Modifier .STATIC ) == 0 ) {
624- IObjectDispenser dispenser = Dispenser .newInstance (objectFactory );
625- BasicAttributes basic = new BasicAttributes (clazz , dataProviderClass );
626- CreationAttributes attributes = new CreationAttributes (context , basic , null );
627- instanceToUse = dispenser .dispense (attributes );
628- } else {
629- instanceToUse = instance ;
630- }
631- // Not a static method but no instance exists, then create new one if possible
632- if ((m .getModifiers () & Modifier .STATIC ) == 0 && instanceToUse == null ) {
633- try {
634- instanceToUse = objectFactory .newInstance (cls );
635- } catch (TestNGException e ) {
636- instanceToUse = null ;
637- }
621+ boolean proceed = null != dp && name .equals (getDataProviderName (dp , m ));
622+ if (!proceed ) {
623+ continue ;
624+ }
625+ Object instanceToUse = instance ;
626+ if (shouldBeStatic && (m .getModifiers () & Modifier .STATIC ) == 0 ) {
627+ IObjectDispenser dispenser = Dispenser .newInstance (objectFactory );
628+ BasicAttributes basic = new BasicAttributes (clazz , dataProviderClass );
629+ CreationAttributes attributes = new CreationAttributes (context , basic , null );
630+ instanceToUse = dispenser .dispense (attributes );
631+ }
632+ // Not a static method but no instance exists, then create new one if possible
633+ if ((m .getModifiers () & Modifier .STATIC ) == 0 && instanceToUse == null ) {
634+ try {
635+ instanceToUse = objectFactory .newInstance (cls );
636+ } catch (TestNGException ignored ) {
638637 }
638+ }
639639
640- if (result != null ) {
641- throw new TestNGException ("Found two providers called '" + name + "' on " + cls );
642- }
640+ if (result != null ) {
641+ throw new TestNGException ("Found two providers called '" + name + "' on " + cls );
642+ }
643643
644- if (isDynamicDataProvider ) {
645- result = new DataProviderMethodRemovable (instanceToUse , m , dp );
646- } else {
647- result = new DataProviderMethod (instanceToUse , m , dp );
648- }
644+ if (isDynamicDataProvider ) {
645+ result = new DataProviderMethodRemovable (instanceToUse , m , dp );
646+ } else {
647+ result = new DataProviderMethod (instanceToUse , m , dp );
649648 }
650649 }
651650
@@ -780,31 +779,46 @@ public static ParameterHolder handleParameters(
780779 String n = "param" + i ;
781780 allParameterNames .put (n , n );
782781 }
783-
784- for (IDataProviderListener dataProviderListener : holder .getListeners ()) {
785- dataProviderListener .beforeDataProviderExecution (
786- dataProviderMethod , testMethod , methodParams .context );
782+ Class <?> retryClass = dataProviderMethod .retryUsing ();
783+ boolean shouldRetry = !retryClass .equals (IRetryDataProvider .DisableDataProviderRetries .class );
784+ IRetryDataProvider retry = null ;
785+ if (shouldRetry ) {
786+ IObjectDispenser dispenser = Dispenser .newInstance (objectFactory );
787+ BasicAttributes basic = new BasicAttributes (testMethod .getTestClass (), retryClass );
788+ CreationAttributes attributes = new CreationAttributes (methodParams .context , basic , null );
789+ retry = (IRetryDataProvider ) dispenser .dispense (attributes );
787790 }
788791
789- Iterator <Object []> initParams ;
790- try {
791- initParams =
792- MethodInvocationHelper .invokeDataProvider (
793- dataProviderMethod
794- .getInstance (), /* a test instance or null if the data provider is static*/
795- dataProviderMethod .getMethod (),
796- testMethod ,
797- methodParams .context ,
798- fedInstance ,
799- annotationFinder );
800- } catch (RuntimeException e ) {
801- for (IDataProviderListener each : holder .getListeners ()) {
802- each .onDataProviderFailure (testMethod , methodParams .context , e );
792+ Iterator <Object []> initParams = null ;
793+ do {
794+
795+ for (IDataProviderListener dataProviderListener : holder .getListeners ()) {
796+ dataProviderListener .beforeDataProviderExecution (
797+ dataProviderMethod , testMethod , methodParams .context );
803798 }
804- throw e ;
805- }
806799
807- final Iterator <Object []> parameters = initParams ;
800+ try {
801+ initParams =
802+ MethodInvocationHelper .invokeDataProvider (
803+ dataProviderMethod
804+ .getInstance (), /* a test instance or null if the data provider is static*/
805+ dataProviderMethod .getMethod (),
806+ testMethod ,
807+ methodParams .context ,
808+ fedInstance ,
809+ annotationFinder );
810+ shouldRetry = false ;
811+ } catch (RuntimeException e ) {
812+ for (IDataProviderListener each : holder .getListeners ()) {
813+ each .onDataProviderFailure (testMethod , methodParams .context , e );
814+ }
815+ if (shouldRetry ) {
816+ shouldRetry = retry .retry (dataProviderMethod );
817+ } else {
818+ throw e ;
819+ }
820+ }
821+ } while (shouldRetry );
808822
809823 for (IDataProviderListener dataProviderListener : holder .getListeners ()) {
810824 dataProviderListener .afterDataProviderExecution (
@@ -817,45 +831,7 @@ public static ParameterHolder handleParameters(
817831 allIndices .addAll (dataProviderMethod .getIndices ());
818832
819833 Iterator <Object []> filteredParameters =
820- new Iterator <Object []>() {
821- int index = 0 ;
822- boolean hasWarn = false ;
823-
824- @ Override
825- public boolean hasNext () {
826- if (index == 0 && !parameters .hasNext () && !hasWarn ) {
827- hasWarn = true ;
828- String msg =
829- String .format (
830- "The test method '%s' will be skipped since its "
831- + "data provider '%s' "
832- + "returned an empty array or iterator. " ,
833- testMethod .getQualifiedName (), dataProviderMethod .getName ());
834- Utils .warn (msg );
835- }
836- return parameters .hasNext ();
837- }
838-
839- @ Override
840- public Object [] next () {
841- testMethod .setParameterInvocationCount (index );
842- Object [] next = parameters .next ();
843- if (next == null ) {
844- throw new TestNGException ("Parameters must not be null" );
845- }
846- if (!allIndices .isEmpty () && !allIndices .contains (index )) {
847- // Skip parameters
848- next = null ;
849- }
850- index ++;
851- return next ;
852- }
853-
854- @ Override
855- public void remove () {
856- throw new UnsupportedOperationException ("remove" );
857- }
858- };
834+ new FilteredParameters (initParams , testMethod , dataProviderMethod .getName (), allIndices );
859835
860836 testMethod .setMoreInvocationChecker (filteredParameters ::hasNext );
861837 for (IDataProviderInterceptor interceptor : holder .getInterceptors ()) {
@@ -919,18 +895,6 @@ public static Object[] injectParameters(
919895 return matcher .getConformingArguments ();
920896 }
921897
922- public static Object [] getParametersFromIndex (Iterator <Object []> parametersValues , int index ) {
923- while (parametersValues .hasNext ()) {
924- Object [] parameters = parametersValues .next ();
925-
926- if (index == 0 ) {
927- return parameters ;
928- }
929- index --;
930- }
931- return null ;
932- }
933-
934898 /** A parameter passing helper class. */
935899 public static class MethodParameters {
936900 private final Map <String , String > xmlParameters ;
0 commit comments