forked from testng-team/testng
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request testng-team#923 from nitinverma/feat-data-providers
Fixes: Array in dataProvider not matching Varargs parameter testng-team#122 testng-team#920
- Loading branch information
Showing
21 changed files
with
1,894 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,3 +26,5 @@ test-output-tests | |
testng.iml | ||
z_build | ||
.kobalt | ||
.DS_Store | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.testng.internal; | ||
|
||
/** | ||
* For boolean use cases were 'non-existence' can not be defaulted to either true or false. | ||
* | ||
* @author <a href="mailto:[email protected]">Nitin Verma</a> | ||
*/ | ||
public enum ThreeStateBoolean { | ||
NONE, TRUE, FALSE; | ||
} |
50 changes: 50 additions & 0 deletions
50
src/main/java/org/testng/internal/reflect/AbstractMethodMatcher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package org.testng.internal.reflect; | ||
|
||
import org.testng.internal.ThreeStateBoolean; | ||
|
||
import static org.testng.internal.ThreeStateBoolean.FALSE; | ||
import static org.testng.internal.ThreeStateBoolean.TRUE; | ||
|
||
/** | ||
* Created on 1/4/16. | ||
* | ||
* @author <a href="mailto:[email protected]">Nitin Verma</a> | ||
*/ | ||
public abstract class AbstractMethodMatcher implements MethodMatcher { | ||
private final MethodMatcherContext context; | ||
private ThreeStateBoolean conforms = ThreeStateBoolean.NONE; | ||
|
||
public AbstractMethodMatcher(final MethodMatcherContext context) { | ||
this.context = context; | ||
} | ||
|
||
protected MethodMatcherContext getContext() { | ||
return context; | ||
} | ||
|
||
protected ThreeStateBoolean getConforms() { | ||
return conforms; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
public boolean conforms() { | ||
boolean hasConformance = false; | ||
try { | ||
hasConformance = hasConformance(); | ||
} finally { | ||
conforms = hasConformance ? TRUE : FALSE; | ||
} | ||
return hasConformance; | ||
} | ||
|
||
/** | ||
* Checks if the arguments conform to the method. | ||
* | ||
* @return conformance | ||
* @throws MethodMatcherException if any internal failure. | ||
*/ | ||
protected abstract boolean hasConformance(); | ||
} |
93 changes: 93 additions & 0 deletions
93
src/main/java/org/testng/internal/reflect/AbstractNodeMethodMatcher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package org.testng.internal.reflect; | ||
|
||
import org.testng.internal.ThreeStateBoolean; | ||
|
||
import java.util.List; | ||
import java.util.Set; | ||
|
||
/** | ||
* Created on 1/4/16. | ||
* | ||
* @author <a href="mailto:[email protected]">Nitin Verma</a> | ||
*/ | ||
public abstract class AbstractNodeMethodMatcher extends AbstractMethodMatcher { | ||
|
||
private Parameter[] conformingParameters = null; | ||
private Set<InjectableParameter> conformingInjects = null; | ||
|
||
public AbstractNodeMethodMatcher(final MethodMatcherContext context) { | ||
super(context); | ||
} | ||
|
||
protected Parameter[] getConformingParameters() { | ||
return conformingParameters; | ||
} | ||
|
||
protected Set<InjectableParameter> getConformingInjects() { | ||
return conformingInjects; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
protected boolean hasConformance() { | ||
boolean matching = false; | ||
for (final Set<InjectableParameter> injects : getConformanceInjectsOrder()) { | ||
final Parameter[] parameters = ReflectionRecipes.filter(getContext().getMethodParameter(), injects); | ||
matching = match(parameters, getContext().getArguments()); | ||
if (matching) { | ||
conformingParameters = parameters; | ||
conformingInjects = injects; | ||
break; | ||
} | ||
} | ||
return matching; | ||
} | ||
|
||
/** | ||
* @return injects to check against. | ||
*/ | ||
protected abstract List<Set<InjectableParameter>> getConformanceInjectsOrder(); | ||
|
||
/** | ||
* Checks if its possible to gives an array consumable by java method invoker. | ||
* | ||
* @param parameters array of parameter instances under question. | ||
* @param arguments instances to be verified. | ||
* @return matches or not | ||
*/ | ||
protected abstract boolean match(final Parameter[] parameters, final Object[] arguments); | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
public Object[] getConformingArguments() throws MethodMatcherException { | ||
if (ThreeStateBoolean.NONE.equals(getConforms())) { | ||
conforms(); | ||
} | ||
if (getConformingParameters() == null) { | ||
throw new MethodMatcherException(this.getClass().getSimpleName() + " mismatch", getContext().getMethod(), | ||
getContext().getArguments()); | ||
} | ||
|
||
return ReflectionRecipes.inject( | ||
getContext().getMethodParameter(), | ||
InjectableParameter.Assistant.ALL_INJECTS, | ||
matchingArguments(getConformingParameters(), getContext().getArguments()), | ||
getContext().getMethod(), | ||
getContext().getTestContext(), | ||
getContext().getTestResult() | ||
); | ||
} | ||
|
||
/** | ||
* If possible gives an array consumable by java method invoker. | ||
* | ||
* @param parameters array of parameter instances under question. | ||
* @param arguments instances to conform. | ||
* @return conforming argument array | ||
*/ | ||
protected abstract Object[] matchingArguments(final Parameter[] parameters, final Object[] arguments); | ||
} |
60 changes: 60 additions & 0 deletions
60
src/main/java/org/testng/internal/reflect/ArrayEndingMethodMatcher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package org.testng.internal.reflect; | ||
|
||
import java.lang.reflect.Array; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import static org.testng.internal.reflect.InjectableParameter.Assistant.ALL_INJECTS; | ||
|
||
/** | ||
* Checks for array ending method argument match with or without filtering injectables. | ||
* | ||
* @author <a href="mailto:[email protected]">Nitin Verma</a> | ||
* @see ReflectionRecipes#matchArrayEnding(Class[], Object[]) | ||
*/ | ||
public class ArrayEndingMethodMatcher extends AbstractNodeMethodMatcher { | ||
|
||
public ArrayEndingMethodMatcher(final MethodMatcherContext context) { | ||
super(context); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
protected List<Set<InjectableParameter>> getConformanceInjectsOrder() { | ||
final List<Set<InjectableParameter>> injectsOrder = new ArrayList<>(1); | ||
injectsOrder.add(ALL_INJECTS); | ||
return injectsOrder; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* @see ReflectionRecipes#matchArrayEnding(Class[], Object[]) | ||
*/ | ||
@Override | ||
protected boolean match(final Parameter[] parameters, final Object[] arguments) { | ||
return ReflectionRecipes.matchArrayEnding(parameters, getContext().getArguments()); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
protected Object[] matchingArguments(final Parameter[] parameters, final Object[] arguments) { | ||
final Class<?>[] classes = ReflectionRecipes.classesFromParameters(parameters); | ||
final Object[] objects = new Object[classes.length]; | ||
final Class<?> componentType = classes[classes.length - 1].getComponentType(); | ||
final Object array = Array.newInstance(componentType, arguments.length - classes.length + 1); | ||
System.arraycopy(arguments, 0, objects, 0, classes.length - 1); | ||
int j = 0; | ||
for (int i = classes.length - 1; i < arguments.length; i++, j++) { | ||
Array.set(array, j, arguments[i]); | ||
} | ||
objects[classes.length - 1] = array; | ||
return objects; | ||
} | ||
|
||
} |
54 changes: 54 additions & 0 deletions
54
src/main/java/org/testng/internal/reflect/DataProviderMethodMatcher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package org.testng.internal.reflect; | ||
|
||
import org.testng.internal.ThreeStateBoolean; | ||
|
||
import static org.testng.internal.ThreeStateBoolean.FALSE; | ||
import static org.testng.internal.ThreeStateBoolean.TRUE; | ||
|
||
/** | ||
* Checks the conformance as per data-provide specifications. | ||
* | ||
* @author <a href="mailto:[email protected]">Nitin Verma</a> | ||
*/ | ||
public class DataProviderMethodMatcher extends AbstractMethodMatcher { | ||
|
||
private final DirectMethodMatcher directMethodMatcher; | ||
private final ArrayEndingMethodMatcher arrayEndingMethodMatcher; | ||
private MethodMatcher matchingMatcher = null; | ||
|
||
public DataProviderMethodMatcher(final MethodMatcherContext context) { | ||
super(context); | ||
this.directMethodMatcher = new DirectMethodMatcher(context); | ||
this.arrayEndingMethodMatcher = new ArrayEndingMethodMatcher(context); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
protected boolean hasConformance() { | ||
boolean matching = false; | ||
if (directMethodMatcher.conforms()) { | ||
matching = true; | ||
matchingMatcher = directMethodMatcher; | ||
} else if (arrayEndingMethodMatcher.conforms()) { | ||
matching = true; | ||
matchingMatcher = arrayEndingMethodMatcher; | ||
} | ||
return matching; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
public Object[] getConformingArguments() throws MethodMatcherException { | ||
if (ThreeStateBoolean.NONE.equals(getConforms())) { | ||
conforms(); | ||
} | ||
if (matchingMatcher != null) { | ||
return matchingMatcher.getConformingArguments(); | ||
} | ||
throw new MethodMatcherException("Data provider mismatch", getContext().getMethod(), getContext().getArguments()); | ||
} | ||
} |
Oops, something went wrong.