@@ -61,6 +61,10 @@ protected int estimateNumIterations(@Nullable Object dataProvider) {
6161 return UNKNOWN_ITERATIONS ;
6262 }
6363
64+ if (dataProvider == null ) {
65+ return UNKNOWN_ITERATIONS ;
66+ }
67+
6468 // an IDataIterator probably already has the estimated size
6569 // or knows better how to calculate it
6670 if (dataProvider instanceof IDataIterator ) {
@@ -107,18 +111,21 @@ protected int estimateNumIterations(Object[] dataProviders) {
107111 }
108112
109113 protected boolean haveNext (Iterator <?>[] iterators , List <DataProviderInfo > dataProviderInfos ) {
114+ Assert .that (iterators .length == dataProviderInfos .size ());
110115 boolean result = true ;
111116
112117 for (int i = 0 ; i < iterators .length ; i ++)
113118 try {
114- boolean hasNext = iterators [i ].hasNext ();
115119 if (i == 0 ) {
116- result = hasNext ;
117- } else if (result != hasNext ) {
118- DataProviderInfo provider = dataProviderInfos .get (i );
119- supervisor .error (context .getErrorInfoCollector (), new ErrorInfo (provider .getDataProviderMethod (),
120- createDifferentNumberOfDataValuesException (provider , hasNext ), getErrorContext ()));
121- return false ;
120+ result = iterators [0 ].hasNext ();
121+ } else if (iterators [i ] != null ) {
122+ boolean hasNext = iterators [i ].hasNext ();
123+ if (result != hasNext ) {
124+ DataProviderInfo provider = dataProviderInfos .get (i );
125+ supervisor .error (context .getErrorInfoCollector (), new ErrorInfo (provider .getDataProviderMethod (),
126+ createDifferentNumberOfDataValuesException (provider , hasNext ), getErrorContext ()));
127+ return false ;
128+ }
122129 }
123130
124131 } catch (Throwable t ) {
@@ -353,6 +360,9 @@ public FeatureDataProviderIterator(IRunSupervisor supervisor, SpockExecutionCont
353360 dataVariableNames = dataVariableNames ();
354361 dataProviders = createDataProviders ();
355362 dataProviderIterators = createDataProviderIterators ();
363+ if ((dataProviderIterators != null ) && (dataProviders != null )) {
364+ Assert .that (dataProviderIterators .length == dataProviders .length );
365+ }
356366 estimatedNumIterations = estimateNumIterations (dataProviderIterators );
357367 }
358368
@@ -380,12 +390,16 @@ public Object[] next() {
380390 if (context .getErrorInfoCollector ().hasErrors ()) {
381391 return null ;
382392 }
393+ Assert .that (dataProviders .length == context .getCurrentFeature ().getDataProviders ().size ());
383394 firstIteration = false ;
384395
385396 // advances iterators and computes args
386397 Object [] next = new Object [dataProviders .length ];
387398 for (int i = 0 ; i < dataProviders .length ; ) {
388399 try {
400+ if (dataProviderIterators [i ] == null ) {
401+ continue ;
402+ }
389403 // if the filter block excluded an iteration
390404 // this might be called after the last iteration
391405 // so just return null if no further data is available
@@ -476,14 +490,14 @@ private IDataIterator[] createDataProviderIterators() {
476490 }
477491
478492 List <DataProviderInfo > dataProviderInfos = context .getCurrentFeature ().getDataProviders ();
479- List < IDataIterator > dataIterators = new ArrayList <>( dataProviders .length ) ;
493+ IDataIterator [] dataIterators = new IDataIterator [ dataProviders .length ] ;
480494 for (int dataProviderIndex = 0 , dataVariableNameIndex = 0 ; dataProviderIndex < dataProviders .length ; dataProviderIndex ++, dataVariableNameIndex ++) {
481495 String nextDataVariableName = dataVariableNames .get (dataVariableNameIndex );
482496 if ((nextDataVariableMultiplication != null )
483497 && (nextDataVariableMultiplication .getDataVariables ()[0 ].equals (nextDataVariableName ))) {
484498
485499 // a cross multiplication starts
486- dataIterators . add ( createDataProviderMultiplier (nextDataVariableMultiplication , dataProviderIndex ) );
500+ dataIterators [ dataProviderIndex ] = createDataProviderMultiplier (nextDataVariableMultiplication , dataProviderIndex );
487501 // skip processed providers and variables
488502 int remainingVariables = nextDataVariableMultiplication .getDataVariables ().length ;
489503 dataVariableNameIndex += remainingVariables - 1 ;
@@ -497,12 +511,14 @@ private IDataIterator[] createDataProviderIterators() {
497511 nextDataVariableMultiplication = dataVariableMultiplications .hasNext () ? dataVariableMultiplications .next () : null ;
498512 } else {
499513 // not a cross multiplication, just use a data provider iterator
500- dataIterators .add (new DataProviderIterator (
514+ DataProviderInfo dataProviderInfo = dataProviderInfos .get (dataProviderIndex );
515+ dataIterators [dataProviderIndex ] = new DataProviderIterator (
501516 supervisor , context , nextDataVariableName ,
502- dataProviderInfos .get (dataProviderIndex ), dataProviders [dataProviderIndex ]));
517+ dataProviderInfo , dataProviders [dataProviderIndex ]);
518+ dataVariableNameIndex += dataProviderInfo .getDataVariables ().size () - 1 ;
503519 }
504520 }
505- return dataIterators . toArray ( new IDataIterator [ 0 ]) ;
521+ return dataIterators ;
506522 }
507523
508524 /**
@@ -534,6 +550,7 @@ private DataProviderMultiplier createDataProviderMultiplier(DataVariableMultipli
534550
535551 return new DataProviderMultiplier (supervisor , context ,
536552 Arrays .asList (dataVariableMultiplication .getDataVariables ()),
553+ multiplierProvider .multiplierProviderInfos .subList (0 , 1 ),
537554 multiplicandProviderInfos , multiplierProvider ,
538555 multiplicandProviders .toArray (new Object [0 ]));
539556 } else {
@@ -610,9 +627,9 @@ public DataProviderIterator(IRunSupervisor supervisor, SpockExecutionContext con
610627 DataProviderInfo providerInfo , Object provider ) {
611628 super (supervisor , context );
612629 this .dataVariableNames = singletonList (Objects .requireNonNull (dataVariableName ));
613- estimatedNumIterations = estimateNumIterations (Objects . requireNonNull ( provider ) );
630+ estimatedNumIterations = estimateNumIterations (provider );
614631 this .providerInfo = Objects .requireNonNull (providerInfo );
615- this .provider = provider ;
632+ this .provider = Objects . requireNonNull ( provider ) ;
616633 iterator = createIterator (provider , providerInfo );
617634 }
618635
@@ -670,8 +687,6 @@ private static class DataProviderMultiplier extends BaseDataIterator {
670687 /**
671688 * The provider infos for the multiplier data providers.
672689 * These are only used for constructing meaningful errors.
673- * If {@link #multiplierProviders} is set, this will be set too,
674- * if it is {@code null}, this will be {@code null} too.
675690 */
676691 private final List <DataProviderInfo > multiplierProviderInfos ;
677692
@@ -788,6 +803,10 @@ public DataProviderMultiplier(IRunSupervisor supervisor, SpockExecutionContext c
788803 multiplierIterators = createIterators (this .multiplierProviders , this .multiplierProviderInfos );
789804 multiplicandIterators = createIterators (this .multiplicandProviders , this .multiplicandProviderInfos );
790805
806+ if (multiplicandIterators != null ) {
807+ Assert .that (multiplicandProviderInfos .size () == multiplicandIterators .length );
808+ }
809+
791810 int estimatedMultiplierIterations = estimateNumIterations (Objects .requireNonNull (multiplierProviders ));
792811 int estimatedMultiplicandIterations = estimateNumIterations (Objects .requireNonNull (multiplicandProviders ));
793812 estimatedNumIterations =
@@ -812,11 +831,11 @@ public DataProviderMultiplier(IRunSupervisor supervisor, SpockExecutionContext c
812831 * @param multiplicandProviders the actual providers for the sets of multiplicand values
813832 */
814833 public DataProviderMultiplier (IRunSupervisor supervisor , SpockExecutionContext context , List <String > dataVariableNames ,
815- List <DataProviderInfo > multiplicandProviderInfos ,
834+ List <DataProviderInfo > multiplierProviderInfos , List < DataProviderInfo > multiplicandProviderInfos ,
816835 DataProviderMultiplier multiplierProvider , Object [] multiplicandProviders ) {
817836 super (supervisor , context );
818837 this .dataVariableNames = Objects .requireNonNull (dataVariableNames );
819- multiplierProviderInfos = null ;
838+ this . multiplierProviderInfos = multiplierProviderInfos ;
820839 this .multiplicandProviderInfos = multiplicandProviderInfos ;
821840 this .multiplierProvider = multiplierProvider ;
822841 multiplierProviders = null ;
@@ -826,6 +845,10 @@ public DataProviderMultiplier(IRunSupervisor supervisor, SpockExecutionContext c
826845 multiplierIterators = new Iterator []{multiplierProvider };
827846 multiplicandIterators = createIterators (this .multiplicandProviders , this .multiplicandProviderInfos );
828847
848+ if (multiplicandIterators != null ) {
849+ Assert .that (multiplicandProviderInfos .size () == multiplicandIterators .length );
850+ }
851+
829852 int estimatedMultiplierIterations = Objects .requireNonNull (multiplierProvider ).getEstimatedNumIterations ();
830853 int estimatedMultiplicandIterations = estimateNumIterations (Objects .requireNonNull (multiplicandProviders ));
831854 estimatedNumIterations =
@@ -943,6 +966,7 @@ private Iterator<?>[] createIterators(Object[] dataProviders, List<DataProviderI
943966 if (context .getErrorInfoCollector ().hasErrors ()) {
944967 return null ;
945968 }
969+ Assert .that (dataProviders .length == dataProviderInfos .size ());
946970
947971 Iterator <?>[] iterators = new Iterator <?>[dataProviders .length ];
948972 for (int i = 0 ; i < dataProviders .length ; i ++) {
@@ -957,6 +981,7 @@ private Iterator<?>[] createIterators(Object[] dataProviders, List<DataProviderI
957981 }
958982
959983 protected Object [] extractNextValues (Iterator <?>[] iterators , List <DataProviderInfo > providerInfos ) {
984+ Assert .that (iterators .length == providerInfos .size ());
960985 Object [] result = new Object [iterators .length ];
961986 for (int i = 0 ; i < iterators .length ; i ++) {
962987 try {
0 commit comments