diff --git a/testng-core-api/src/main/java/org/testng/IFactoryMethod.java b/testng-core-api/src/main/java/org/testng/IFactoryMethod.java index 6b11bef48c..e600ea13a4 100644 --- a/testng-core-api/src/main/java/org/testng/IFactoryMethod.java +++ b/testng-core-api/src/main/java/org/testng/IFactoryMethod.java @@ -1,12 +1,8 @@ package org.testng; -import java.util.Optional; - /** Represents a factory method */ public interface IFactoryMethod { - /** - * @return - Returns parameters associated with a factory method wrapped within a {@link Optional} - */ - Optional getParameters(); + /** @return - Returns parameters associated with a factory method */ + Object[] getParameters(); } diff --git a/testng-core-api/src/main/java/org/testng/IInstanceInfo.java b/testng-core-api/src/main/java/org/testng/IInstanceInfo.java index e965580787..bbd0afd2b8 100644 --- a/testng-core-api/src/main/java/org/testng/IInstanceInfo.java +++ b/testng-core-api/src/main/java/org/testng/IInstanceInfo.java @@ -1,14 +1,15 @@ package org.testng; +import java.util.UUID; + /** * This class defines a pair of instance/class. A method with @Factory can return an array of these * objects instead of Object[] so that instances can be dynamic proxies or mock objects and still * provide enough information to TestNG to figure out what classes the annotations should be looked * up in. - * - * @author Cedric Beust */ public interface IInstanceInfo { + UUID getUid(); /** @return The instance on which the tests will be invoked. */ T getInstance(); diff --git a/testng-core-api/src/main/java/org/testng/IMethodInstance.java b/testng-core-api/src/main/java/org/testng/IMethodInstance.java index 5a181db231..deb2d455a8 100644 --- a/testng-core-api/src/main/java/org/testng/IMethodInstance.java +++ b/testng-core-api/src/main/java/org/testng/IMethodInstance.java @@ -5,5 +5,6 @@ public interface IMethodInstance { ITestNGMethod getMethod(); + // TODO deprecate return IInstanceInfo Object getInstance(); } diff --git a/testng-core-api/src/main/java/org/testng/ITestClassInstance.java b/testng-core-api/src/main/java/org/testng/ITestClassInstance.java index 509b609599..76a307a43c 100644 --- a/testng-core-api/src/main/java/org/testng/ITestClassInstance.java +++ b/testng-core-api/src/main/java/org/testng/ITestClassInstance.java @@ -1,10 +1,7 @@ package org.testng; /** Represents the ability to retrieve the parameters associated with a factory method. */ -public interface ITestClassInstance { - - /** @return - The actual instance associated with a factory method */ - T getInstance(); +public interface ITestClassInstance extends IInstanceInfo { /** * @return - The actual index of instance associated with a factory method. This index has a 1:1 @@ -24,6 +21,8 @@ public interface ITestClassInstance { */ int getInvocationIndex(); + IFactoryMethod getFactoryMethod(); + static Object embeddedInstance(Object original) { if (original instanceof ITestClassInstance) { return ((ITestClassInstance) original).getInstance(); diff --git a/testng-core-api/src/main/java/org/testng/ITestNGMethod.java b/testng-core-api/src/main/java/org/testng/ITestNGMethod.java index add31af349..f227b7a89c 100644 --- a/testng-core-api/src/main/java/org/testng/ITestNGMethod.java +++ b/testng-core-api/src/main/java/org/testng/ITestNGMethod.java @@ -2,7 +2,6 @@ import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.concurrent.Callable; import org.testng.annotations.CustomAttribute; @@ -39,6 +38,7 @@ public interface ITestNGMethod extends Cloneable { */ String getMethodName(); + // TODO deprecate return IInstanceInfo Object getInstance(); /** @@ -266,18 +266,11 @@ default boolean isDataDriven() { * @return - A {@link IParameterInfo} object that represents details about the parameters * associated with the factory method. */ + @Deprecated default IParameterInfo getFactoryMethodParamsInfo() { return null; } - /** - * @return - A {@link IFactoryMethod} implementation that contains attributes associated with a - * factory method, wrapped within an {@link Optional}. - */ - default Optional getFactoryMethod() { - return Optional.empty(); - } - /** * @return - An array of {@link CustomAttribute} that represents the custom attributes associated * with a test. diff --git a/testng-core-api/src/main/java/org/testng/internal/IParameterInfo.java b/testng-core-api/src/main/java/org/testng/internal/IParameterInfo.java index 99ed97cf5f..557fdccdd9 100644 --- a/testng-core-api/src/main/java/org/testng/internal/IParameterInfo.java +++ b/testng-core-api/src/main/java/org/testng/internal/IParameterInfo.java @@ -1,7 +1,6 @@ package org.testng.internal; import org.testng.ITestClassInstance; -import org.testng.ITestNGMethod; /** * Represents the ability to retrieve the parameters associated with a factory method. @@ -9,11 +8,11 @@ * @deprecated - This interface stands deprecated as of TestNG 7.11.0. */ @Deprecated -public interface IParameterInfo extends ITestClassInstance { +public interface IParameterInfo extends ITestClassInstance { /** * @return - The parameters associated with the factory method as an array. * @deprecated - This method stands deprecated as of TestNG 7.11.0 Please use {@link - * ITestNGMethod#getFactoryMethod()} to retrieve the parameters. + * ITestClassInstance#getFactoryMethod()} to retrieve the parameters. */ @Deprecated Object[] getParameters(); diff --git a/testng-core/src/main/java/org/testng/ClassMethodMap.java b/testng-core/src/main/java/org/testng/ClassMethodMap.java index b208647767..09c29769a1 100644 --- a/testng-core/src/main/java/org/testng/ClassMethodMap.java +++ b/testng-core/src/main/java/org/testng/ClassMethodMap.java @@ -16,11 +16,11 @@ * @author Alex Popescu */ public class ClassMethodMap { - private final Map> classMap = Maps.newConcurrentMap(); + private final Map, Collection> classMap = Maps.newConcurrentMap(); // These two variables are used throughout the workers to keep track // of what beforeClass/afterClass methods have been invoked - private final Map> beforeClassMethods = Maps.newConcurrentMap(); - private final Map> afterClassMethods = Maps.newConcurrentMap(); + private final Map>> beforeClassMethods = Maps.newConcurrentMap(); + private final Map>> afterClassMethods = Maps.newConcurrentMap(); public ClassMethodMap(List methods, XmlMethodSelector xmlMethodSelector) { for (ITestNGMethod m : methods) { @@ -31,7 +31,7 @@ public ClassMethodMap(List methods, XmlMethodSelector xmlMethodSe continue; } - Object instance = m.getInstance(); + IInstanceInfo instance = (IInstanceInfo) m.getInstance(); classMap.computeIfAbsent(instance, k -> new ConcurrentLinkedQueue<>()).add(m); } } @@ -43,7 +43,7 @@ public ClassMethodMap(List methods, XmlMethodSelector xmlMethodSe * @param instance The test instance * @return true if it is the last of its class */ - public boolean removeAndCheckIfLast(ITestNGMethod m, Object instance) { + public boolean removeAndCheckIfLast(ITestNGMethod m, IInstanceInfo instance) { Collection l = classMap.get(instance); if (l == null) { throw new IllegalStateException( @@ -60,19 +60,19 @@ public boolean removeAndCheckIfLast(ITestNGMethod m, Object instance) { return true; } - public Map> getInvokedBeforeClassMethods() { + public Map>> getInvokedBeforeClassMethods() { return beforeClassMethods; } - public Map> getInvokedAfterClassMethods() { + public Map>> getInvokedAfterClassMethods() { return afterClassMethods; } public void clear() { - for (Set instances : beforeClassMethods.values()) { + for (Set> instances : beforeClassMethods.values()) { instances.clear(); } - for (Set instances : afterClassMethods.values()) { + for (Set> instances : afterClassMethods.values()) { instances.clear(); } beforeClassMethods.clear(); diff --git a/testng-core/src/main/java/org/testng/DependencyMap.java b/testng-core/src/main/java/org/testng/DependencyMap.java index d998f73d54..dd557d1fa5 100644 --- a/testng-core/src/main/java/org/testng/DependencyMap.java +++ b/testng-core/src/main/java/org/testng/DependencyMap.java @@ -103,49 +103,47 @@ private static boolean belongToDifferentClassHierarchy( private static boolean hasInstance( ITestNGMethod baseClassMethod, ITestNGMethod derivedClassMethod) { - Object baseInstance = baseClassMethod.getInstance(); - Object derivedInstance = derivedClassMethod.getInstance(); + IInstanceInfo baseInstance = (IInstanceInfo) baseClassMethod.getInstance(); + IInstanceInfo derivedInstance = (IInstanceInfo) derivedClassMethod.getInstance(); boolean result = derivedInstance != null || baseInstance != null; - boolean params = - baseClassMethod.getFactoryMethod().flatMap(IFactoryMethod::getParameters).isPresent(); - - if (result && params && RuntimeBehavior.enforceThreadAffinity()) { - return hasSameParameters(baseClassMethod, derivedClassMethod); + if (RuntimeBehavior.enforceThreadAffinity() + && result + && baseClassMethod instanceof ITestClassInstance + && derivedClassMethod instanceof ITestClassInstance) { + return hasSameParameters( + (ITestClassInstance) baseClassMethod, (ITestClassInstance) derivedClassMethod); } return result; } - private static boolean hasSameParameters( - ITestNGMethod baseClassMethod, ITestNGMethod derivedClassMethod) { - Optional first = baseClassMethod.getFactoryMethod(); - Optional second = derivedClassMethod.getFactoryMethod(); - if (first.isPresent() && second.isPresent()) { - Optional firstParams = first.get().getParameters(); - Optional secondParams = second.get().getParameters(); - if (firstParams.isPresent() && secondParams.isPresent()) { - return firstParams.get()[0].equals(secondParams.get()[0]); - } - return false; - } - return false; - } - private static boolean isSameInstance( ITestNGMethod baseClassMethod, ITestNGMethod derivedClassMethod) { - Object baseInstance = baseClassMethod.getInstance(); - Object derivedInstance = derivedClassMethod.getInstance(); + IInstanceInfo baseInstance = (IInstanceInfo) baseClassMethod.getInstance(); + IInstanceInfo derivedInstance = (IInstanceInfo) derivedClassMethod.getInstance(); boolean nonNullInstances = derivedInstance != null && baseInstance != null; if (!nonNullInstances) { return false; } - if (null != baseClassMethod.getFactoryMethodParamsInfo() - && RuntimeBehavior.enforceThreadAffinity()) { + if (RuntimeBehavior.enforceThreadAffinity() + && baseClassMethod instanceof ITestClassInstance + && derivedClassMethod instanceof ITestClassInstance) { return baseInstance.getClass().isAssignableFrom(derivedInstance.getClass()) - && hasSameParameters(baseClassMethod, derivedClassMethod); + && hasSameParameters( + (ITestClassInstance) baseClassMethod, (ITestClassInstance) derivedClassMethod); } return baseInstance.getClass().isAssignableFrom(derivedInstance.getClass()); } + private static boolean hasSameParameters( + ITestClassInstance baseClassMethod, ITestClassInstance derivedClassMethod) { + Object[] firstParams = baseClassMethod.getFactoryMethod().getParameters(); + Object[] secondParams = derivedClassMethod.getFactoryMethod().getParameters(); + if (firstParams.length == 0 || secondParams.length == 0) { + return false; + } + return firstParams[0].equals(secondParams[0]); + } + private static String constructMethodNameUsingTestClass( String currentMethodName, ITestNGMethod m) { int lastIndex = currentMethodName.lastIndexOf('.'); diff --git a/testng-core/src/main/java/org/testng/InstanceOrderingMethodInterceptor.java b/testng-core/src/main/java/org/testng/InstanceOrderingMethodInterceptor.java index b3f65ba11c..be9eff3bda 100644 --- a/testng-core/src/main/java/org/testng/InstanceOrderingMethodInterceptor.java +++ b/testng-core/src/main/java/org/testng/InstanceOrderingMethodInterceptor.java @@ -15,10 +15,10 @@ public List intercept(List methods, ITestConte /** The default method interceptor which sorts methods by instances (i.e. by class). */ private List groupMethodsByInstance(List methods) { - List instanceList = Lists.newArrayList(); + List> instanceList = Lists.newArrayList(); Map> map = Maps.newLinkedHashMap(); for (IMethodInstance mi : methods) { - Object instance = mi.getInstance(); + IInstanceInfo instance = (IInstanceInfo) mi.getInstance(); if (!instanceList.contains(instance)) { instanceList.add(instance); } diff --git a/testng-core/src/main/java/org/testng/TestClass.java b/testng-core/src/main/java/org/testng/TestClass.java index 518121c49c..7ab9090ca3 100644 --- a/testng-core/src/main/java/org/testng/TestClass.java +++ b/testng-core/src/main/java/org/testng/TestClass.java @@ -29,10 +29,10 @@ class TestClass extends NoOpTestClass implements ITestClass, ITestClassConfigInf private final ITestObjectFactory objectFactory; private final String m_errorMsgPrefix; - private final IdentityHashMap> beforeClassConfig = + private final IdentityHashMap, List> beforeClassConfig = new IdentityHashMap<>(); - private final IdentityHashMap> afterClassConfig = + private final IdentityHashMap, List> afterClassConfig = new IdentityHashMap<>(); @Override @@ -46,7 +46,7 @@ public List getAllAfterClassMethods() { } private static List getAllClassLevelConfigs( - IdentityHashMap> map) { + IdentityHashMap, List> map) { return map.values() .parallelStream() .reduce( @@ -59,12 +59,12 @@ private static List getAllClassLevelConfigs( } @Override - public List getInstanceBeforeClassMethods(Object instance) { + public List getInstanceBeforeClassMethods(IInstanceInfo instance) { return beforeClassConfig.get(instance); } @Override - public List getInstanceAfterClassMethods(Object instance) { + public List getInstanceAfterClassMethods(IInstanceInfo instance) { return afterClassConfig.get(instance); } @@ -123,10 +123,9 @@ private void initTestClassesAndInstances() { // // TestClasses and instances // - IObject.IdentifiableObject[] instances = getObjects(true, this.m_errorMsgPrefix); + IInstanceInfo[] instances = getObjects(true, this.m_errorMsgPrefix); Arrays.stream(instances) - .map(IdentifiableObject::getInstance) - .map(ITestClassInstance::embeddedInstance) + .map(IInstanceInfo::getInstance) .filter(it -> it instanceof ITest) .findFirst() .ifPresent(it -> testName = ((ITest) it).getTestName()); @@ -146,7 +145,7 @@ public Object[] getInstances(boolean create, String errorMsgPrefix) { } @Override - public IObject.IdentifiableObject[] getObjects(boolean create, String errorMsgPrefix) { + public IInstanceInfo[] getObjects(boolean create, String errorMsgPrefix) { return IObject.objects(iClass, create, errorMsgPrefix); } @@ -161,7 +160,7 @@ public void addInstance(Object instance) { } @Override - public void addObject(IObject.IdentifiableObject instance) { + public void addObject(IInstanceInfo instance) { IObject.cast(iClass).ifPresent(it -> it.addObject(instance)); } @@ -169,21 +168,21 @@ private void initMethods() { ITestNGMethod[] methods = testMethodFinder.getTestMethods(m_testClass, xmlTest); m_testMethods = createTestMethods(methods); - for (IdentifiableObject eachInstance : IObject.objects(iClass, false)) { + for (IInstanceInfo instance : IObject.objects(iClass, false)) { m_beforeSuiteMethods = ConfigurationMethod.createSuiteConfigurationMethods( objectFactory, testMethodFinder.getBeforeSuiteMethods(m_testClass), annotationFinder, true, - eachInstance); + instance); m_afterSuiteMethods = ConfigurationMethod.createSuiteConfigurationMethods( objectFactory, testMethodFinder.getAfterSuiteMethods(m_testClass), annotationFinder, false, - eachInstance); + instance); m_beforeTestConfMethods = ConfigurationMethod.createTestConfigurationMethods( objectFactory, @@ -191,7 +190,7 @@ private void initMethods() { annotationFinder, true, this.xmlTest, - eachInstance); + instance); m_afterTestConfMethods = ConfigurationMethod.createTestConfigurationMethods( objectFactory, @@ -199,7 +198,7 @@ private void initMethods() { annotationFinder, false, this.xmlTest, - eachInstance); + instance); m_beforeClassMethods = ConfigurationMethod.createClassConfigurationMethods( objectFactory, @@ -207,8 +206,7 @@ private void initMethods() { annotationFinder, true, xmlTest, - eachInstance); - Object instance = ITestClassInstance.embeddedInstance(eachInstance.getInstance()); + instance); beforeClassConfig.put(instance, m_beforeClassMethods); m_afterClassMethods = ConfigurationMethod.createClassConfigurationMethods( @@ -217,7 +215,7 @@ private void initMethods() { annotationFinder, false, xmlTest, - eachInstance); + instance); afterClassConfig.put(instance, m_afterClassMethods); m_beforeGroupsMethods = ConfigurationMethod.createBeforeConfigurationMethods( @@ -225,14 +223,14 @@ private void initMethods() { testMethodFinder.getBeforeGroupsConfigurationMethods(m_testClass), annotationFinder, true, - eachInstance); + instance); m_afterGroupsMethods = ConfigurationMethod.createAfterConfigurationMethods( objectFactory, testMethodFinder.getAfterGroupsConfigurationMethods(m_testClass), annotationFinder, false, - eachInstance); + instance); m_beforeTestMethods.addAll( ConfigurationMethod.createTestMethodConfigurationMethods( objectFactory, @@ -240,7 +238,7 @@ private void initMethods() { annotationFinder, true, xmlTest, - eachInstance)); + instance)); m_afterTestMethods.addAll( ConfigurationMethod.createTestMethodConfigurationMethods( objectFactory, @@ -248,7 +246,7 @@ private void initMethods() { annotationFinder, false, xmlTest, - eachInstance)); + instance)); } } @@ -261,9 +259,10 @@ private ITestNGMethod[] createTestMethods(ITestNGMethod[] methods) { for (ITestNGMethod tm : methods) { ConstructorOrMethod m = tm.getConstructorOrMethod(); if (m.getDeclaringClass().isAssignableFrom(m_testClass)) { - for (IdentifiableObject o : IObject.objects(iClass, false)) { + for (IInstanceInfo instance : IObject.objects(iClass, false)) { log(4, "Adding method " + tm + " on TestClass " + m_testClass); - vResult.add(new TestNGMethod(objectFactory, m.getMethod(), annotationFinder, xmlTest, o)); + vResult.add( + new TestNGMethod(objectFactory, m.getMethod(), annotationFinder, xmlTest, instance)); } } else { log(4, "Rejecting method " + tm + " for TestClass " + m_testClass); diff --git a/testng-core/src/main/java/org/testng/internal/BaseClassFinder.java b/testng-core/src/main/java/org/testng/internal/BaseClassFinder.java index 75af20b88b..0101924ef4 100644 --- a/testng-core/src/main/java/org/testng/internal/BaseClassFinder.java +++ b/testng-core/src/main/java/org/testng/internal/BaseClassFinder.java @@ -2,6 +2,7 @@ import java.util.Map; import org.testng.IClass; +import org.testng.IInstanceInfo; import org.testng.ITestClassFinder; import org.testng.ITestContext; import org.testng.ITestObjectFactory; @@ -32,7 +33,7 @@ protected IClass findOrCreateIClass( ITestContext context, Class cls, XmlClass xmlClass, - IObject.IdentifiableObject instance, + IInstanceInfo instance, IAnnotationFinder annotationFinder, ITestObjectFactory objectFactory) { diff --git a/testng-core/src/main/java/org/testng/internal/BaseTestMethod.java b/testng-core/src/main/java/org/testng/internal/BaseTestMethod.java index 28765c8350..63ec1ad89f 100644 --- a/testng-core/src/main/java/org/testng/internal/BaseTestMethod.java +++ b/testng-core/src/main/java/org/testng/internal/BaseTestMethod.java @@ -8,7 +8,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,10 +16,9 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import org.testng.IClass; -import org.testng.IFactoryMethod; +import org.testng.IInstanceInfo; import org.testng.IRetryAnalyzer; import org.testng.ITestClass; -import org.testng.ITestClassInstance; import org.testng.ITestNGMethod; import org.testng.ITestObjectFactory; import org.testng.ITestResult; @@ -38,8 +36,7 @@ import org.testng.xml.XmlTest; /** Superclass to represent both @Test and @Configuration methods. */ -public abstract class BaseTestMethod - implements ITestNGMethod, IInvocationStatus, IInstanceIdentity { +public abstract class BaseTestMethod implements ITestNGMethod, IInvocationStatus { private static final Pattern SPACE_SEPARATOR_PATTERN = Pattern.compile(" +"); @@ -86,7 +83,7 @@ public abstract class BaseTestMethod private int m_interceptedPriority; private XmlTest m_xmlTest; - private final IObject.IdentifiableObject m_instance; + private final IInstanceInfo m_instance; private final Map m_testMethodToRetryAnalyzer = Maps.newConcurrentMap(); protected final ITestObjectFactory m_objectFactory; @@ -96,7 +93,7 @@ public BaseTestMethod( String methodName, ConstructorOrMethod com, IAnnotationFinder annotationFinder, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { m_objectFactory = objectFactory; m_methodClass = com.getDeclaringClass(); m_method = com; @@ -105,10 +102,6 @@ public BaseTestMethod( m_instance = instance; } - protected final IObject.IdentifiableObject identifiableObject() { - return m_instance; - } - /** {@inheritDoc} */ @Override public boolean isAlwaysRun() { @@ -156,18 +149,8 @@ public String getMethodName() { } @Override - public Object getInstance() { - return Optional.ofNullable(m_instance) - .map(IObject.IdentifiableObject::getInstance) - .map(ITestClassInstance::embeddedInstance) - .orElse(null); - } - - @Override - public UUID getInstanceId() { - return Optional.ofNullable(m_instance) - .map(IObject.IdentifiableObject::getInstanceId) - .orElse(null); + public IInstanceInfo getInstance() { + return m_instance; } /** {@inheritDoc} */ @@ -305,19 +288,6 @@ public void setTimeOut(long timeOut) { m_timeOut = timeOut; } - @Override - public Optional getFactoryMethod() { - IObject.IdentifiableObject identifiable = identifiableObject(); - if (identifiable == null) { - return Optional.empty(); - } - Object instance = identifiableObject().getInstance(); - if (instance instanceof ParameterInfo) { - return Optional.of(() -> Optional.of(((ParameterInfo) instance).getParameters())); - } - return ITestNGMethod.super.getFactoryMethod(); - } - /** * {@inheritDoc} * @@ -398,7 +368,7 @@ public boolean equals(Object obj) { ? other.m_testClass == null : other.m_testClass != null && m_testClass.getRealClass().equals(other.m_testClass.getRealClass()) - && getInstance() == other.getInstance(); + && getInstance().equals(other.getInstance()); return isEqual && getConstructorOrMethod().equals(other.getConstructorOrMethod()); } @@ -412,7 +382,7 @@ public boolean equals(Object obj) { public int hashCode() { int hash = m_method.hashCode(); if (getInstance() != null) { - hash = hash * 31 + System.identityHashCode(getInstance()); + hash = hash * 31 + getInstance().hashCode(); } return hash; } @@ -420,10 +390,10 @@ public int hashCode() { protected void initGroups(Class annotationClass) { ITestOrConfiguration annotation = getAnnotationFinder().findAnnotation(getConstructorOrMethod(), annotationClass); - Object object = getInstance(); + IInstanceInfo object = getInstance(); Class clazz = getConstructorOrMethod().getDeclaringClass(); if (object != null) { - clazz = object.getClass(); + clazz = object.getInstanceClass(); } ITestOrConfiguration classAnnotation = getAnnotationFinder().findAnnotation(clazz, annotationClass); @@ -528,7 +498,6 @@ private String computeSignature() { .append(getPriority()) .append(", instance:") .append(getInstance()) - .append(instanceParameters()) .append(customAttributes()) .append("]"); @@ -556,13 +525,6 @@ public String getSimpleName() { return m_method.getDeclaringClass().getSimpleName() + "." + m_method.getName(); } - private String instanceParameters() { - return getFactoryMethod() - .flatMap(IFactoryMethod::getParameters) - .map(it -> ", instance params:" + Arrays.toString(it)) - .orElse(""); - } - protected String getSignature() { if (m_signature == null) { m_signature = computeSignature(); diff --git a/testng-core/src/main/java/org/testng/internal/ClassImpl.java b/testng-core/src/main/java/org/testng/internal/ClassImpl.java index 2cbc2add19..f8fcbe7338 100644 --- a/testng-core/src/main/java/org/testng/internal/ClassImpl.java +++ b/testng-core/src/main/java/org/testng/internal/ClassImpl.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Map; import org.testng.IClass; +import org.testng.IInstanceInfo; import org.testng.ITest; import org.testng.ITestClassInstance; import org.testng.ITestContext; @@ -25,12 +26,12 @@ public class ClassImpl implements IClass, IObject { private final Class m_class; - private IObject.IdentifiableObject m_defaultInstance = null; + private IInstanceInfo m_defaultInstance = null; private final IAnnotationFinder m_annotationFinder; - private final List identifiableObjects = Lists.newArrayList(); + private final List> identifiableObjects = Lists.newArrayList(); private final Map, IClass> m_classes; private long[] m_instanceHashCodes; - private final IObject.IdentifiableObject m_instance; + private final IInstanceInfo m_instance; private final ITestObjectFactory m_objectFactory; private String m_testName = null; private final XmlClass m_xmlClass; @@ -40,7 +41,7 @@ public ClassImpl( ITestContext context, Class cls, XmlClass xmlClass, - IObject.IdentifiableObject instance, + IInstanceInfo instance, Map, IClass> classes, IAnnotationFinder annotationFinder, ITestObjectFactory objectFactory) { @@ -51,7 +52,7 @@ public ClassImpl( m_annotationFinder = annotationFinder; m_instance = instance; m_objectFactory = objectFactory; - if (IObject.IdentifiableObject.unwrap(instance) instanceof ITest) { + if (instance != null && instance.getInstance() instanceof ITest) { m_testName = ((ITest) instance.getInstance()).getTestName(); } if (m_testName == null) { @@ -92,7 +93,7 @@ public XmlClass getXmlClass() { return m_xmlClass; } - private IObject.IdentifiableObject getDefaultInstance(boolean create, String errMsgPrefix) { + private IInstanceInfo getDefaultInstance(boolean create, String errMsgPrefix) { if (m_defaultInstance == null) { if (m_instance != null) { m_defaultInstance = m_instance; @@ -107,7 +108,7 @@ private IObject.IdentifiableObject getDefaultInstance(boolean create, String err CreationAttributes attributes = new CreationAttributes(m_testContext, basic, detailed); Object raw = dispenser.dispense(attributes); if (raw != null) { - m_defaultInstance = new IObject.IdentifiableObject(raw); + m_defaultInstance = new InstanceInfo<>(raw); } } } @@ -122,26 +123,25 @@ public Object[] getInstances(boolean create) { @Override public Object[] getInstances(boolean create, String errorMsgPrefix) { return Arrays.stream(getObjects(create, errorMsgPrefix)) - .map(IdentifiableObject::getInstance) + .map(IInstanceInfo::getInstance) .toArray(Object[]::new); } @Override - public void addObject(IdentifiableObject instance) { + public void addObject(IInstanceInfo instance) { identifiableObjects.add(instance); } @Override - public IdentifiableObject[] getObjects(boolean create, String errorMsgPrefix) { - IdentifiableObject[] result = {}; - - if (!identifiableObjects.isEmpty()) { - result = identifiableObjects.toArray(new IdentifiableObject[0]); - } else { - IdentifiableObject defaultInstance = getDefaultInstance(create, errorMsgPrefix); + public IInstanceInfo[] getObjects(boolean create, String errorMsgPrefix) { + IInstanceInfo[] result = {}; + if (identifiableObjects.isEmpty()) { + IInstanceInfo defaultInstance = getDefaultInstance(create, errorMsgPrefix); if (defaultInstance != null) { - result = new IdentifiableObject[] {defaultInstance}; + result = new IInstanceInfo[] {defaultInstance}; } + } else { + result = identifiableObjects.toArray(new IInstanceInfo[0]); } int m_instanceCount = identifiableObjects.size(); @@ -159,7 +159,7 @@ public String toString() { @Override public void addInstance(Object instance) { - addObject(new IdentifiableObject(instance)); + addObject(new InstanceInfo<>(instance)); } private static int computeHashCode(Object instance) { diff --git a/testng-core/src/main/java/org/testng/internal/ClonedMethod.java b/testng-core/src/main/java/org/testng/internal/ClonedMethod.java index 55830f3d54..b8bef4dd21 100644 --- a/testng-core/src/main/java/org/testng/internal/ClonedMethod.java +++ b/testng-core/src/main/java/org/testng/internal/ClonedMethod.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.concurrent.Callable; import org.testng.IClass; +import org.testng.IInstanceInfo; import org.testng.IRetryAnalyzer; import org.testng.ITestClass; import org.testng.ITestNGMethod; @@ -94,8 +95,8 @@ public long[] getInstanceHashCodes() { } @Override - public Object getInstance() { - return m_method.getInstance(); + public IInstanceInfo getInstance() { + return (IInstanceInfo) m_method.getInstance(); } @Override diff --git a/testng-core/src/main/java/org/testng/internal/ConfigurationMethod.java b/testng-core/src/main/java/org/testng/internal/ConfigurationMethod.java index f123ec0d77..d4d945551e 100644 --- a/testng-core/src/main/java/org/testng/internal/ConfigurationMethod.java +++ b/testng-core/src/main/java/org/testng/internal/ConfigurationMethod.java @@ -5,8 +5,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.stream.Collectors; +import org.testng.IInstanceInfo; import org.testng.ITestNGMethod; import org.testng.ITestObjectFactory; import org.testng.annotations.IAnnotation; @@ -50,7 +50,6 @@ public class ConfigurationMethod extends BaseTestMethod { private final boolean m_isIgnoreFailure; private boolean m_inheritGroupsFromTestClass = false; - private final IParameterInfo factoryMethodInfo; private ConfigurationMethod( ITestObjectFactory objectFactory, @@ -68,19 +67,12 @@ private ConfigurationMethod( String[] beforeGroups, String[] afterGroups, boolean initialize, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { super(objectFactory, com.getName(), com, annotationFinder, instance); if (initialize) { init(); } - this.factoryMethodInfo = - (IParameterInfo) - Optional.ofNullable(instance) - .map(IObject.IdentifiableObject::getInstance) - .filter(it -> it instanceof IParameterInfo) - .orElse(null); - m_isBeforeSuiteConfiguration = isBeforeSuite; m_isAfterSuiteConfiguration = isAfterSuite; @@ -99,14 +91,6 @@ private ConfigurationMethod( m_afterGroups = afterGroups; } - @Override - public IParameterInfo getFactoryMethodParamsInfo() { - if (this.factoryMethodInfo != null) { - return this.factoryMethodInfo; - } - return super.getFactoryMethodParamsInfo(); - } - public ConfigurationMethod( ITestObjectFactory objectFactory, ConstructorOrMethod com, @@ -123,7 +107,7 @@ public ConfigurationMethod( String[] beforeGroups, String[] afterGroups, XmlTest xmlTest, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { this( objectFactory, com, @@ -157,7 +141,7 @@ private static List createMethods( boolean isBeforeMethod, boolean isAfterMethod, XmlTest xmlTest, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { List result = Lists.newArrayList(); for (ITestNGMethod method : methods) { if (Modifier.isStatic(method.getConstructorOrMethod().getMethod().getModifiers())) { @@ -197,7 +181,7 @@ public static List createSuiteConfigurationMethods( ITestNGMethod[] methods, IAnnotationFinder annotationFinder, boolean isBefore, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { return createMethods( objectFactory, @@ -221,7 +205,7 @@ public static List createTestConfigurationMethods( IAnnotationFinder annotationFinder, boolean isBefore, XmlTest xmlTest, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { return createMethods( objectFactory, methods, @@ -244,7 +228,7 @@ public static List createClassConfigurationMethods( IAnnotationFinder annotationFinder, boolean isBefore, XmlTest xmlTest, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { return createMethods( objectFactory, methods, @@ -266,7 +250,7 @@ public static ITestNGMethod[] createBeforeConfigurationMethods( ITestNGMethod[] methods, IAnnotationFinder annotationFinder, boolean isBefore, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { ITestNGMethod[] result = new ITestNGMethod[methods.length]; for (int i = 0; i < methods.length; i++) { result[i] = @@ -297,7 +281,7 @@ public static List createAfterConfigurationMethods( ITestNGMethod[] methods, IAnnotationFinder annotationFinder, boolean isBefore, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { return Arrays.stream(methods) .parallel() .map( @@ -328,7 +312,7 @@ public static List createTestMethodConfigurationMethods( IAnnotationFinder annotationFinder, boolean isBefore, XmlTest xmlTest, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { return createMethods( objectFactory, methods, @@ -508,7 +492,7 @@ public ConfigurationMethod clone() { getBeforeGroups(), getAfterGroups(), false /* do not call init() */, - new IObject.IdentifiableObject(getInstance(), getInstanceId())); + getInstance()); clone.m_testClass = getTestClass(); clone.setDate(getDate()); clone.setGroups(getGroups()); diff --git a/testng-core/src/main/java/org/testng/internal/DataProviderMethod.java b/testng-core/src/main/java/org/testng/internal/DataProviderMethod.java index 2fca52ad42..8d53b1ab19 100644 --- a/testng-core/src/main/java/org/testng/internal/DataProviderMethod.java +++ b/testng-core/src/main/java/org/testng/internal/DataProviderMethod.java @@ -3,17 +3,18 @@ import java.lang.reflect.Method; import java.util.List; import org.testng.IDataProviderMethod; +import org.testng.IInstanceInfo; import org.testng.IRetryDataProvider; import org.testng.annotations.IDataProviderAnnotation; /** Represents an @{@link org.testng.annotations.DataProvider} annotated method. */ class DataProviderMethod implements IDataProviderMethod { - protected Object instance; + protected IInstanceInfo instance; protected Method method; private final IDataProviderAnnotation annotation; - DataProviderMethod(Object instance, Method method, IDataProviderAnnotation annotation) { + DataProviderMethod(IInstanceInfo instance, Method method, IDataProviderAnnotation annotation) { this.instance = instance; this.method = method; this.annotation = annotation; @@ -21,7 +22,8 @@ class DataProviderMethod implements IDataProviderMethod { @Override public Object getInstance() { - return instance; + // TODO return instance + return instance.getInstance(); } @Override diff --git a/testng-core/src/main/java/org/testng/internal/DataProviderMethodRemovable.java b/testng-core/src/main/java/org/testng/internal/DataProviderMethodRemovable.java index b4c1a98171..e206be17b7 100644 --- a/testng-core/src/main/java/org/testng/internal/DataProviderMethodRemovable.java +++ b/testng-core/src/main/java/org/testng/internal/DataProviderMethodRemovable.java @@ -1,16 +1,18 @@ package org.testng.internal; import java.lang.reflect.Method; +import org.testng.IInstanceInfo; import org.testng.annotations.IDataProviderAnnotation; /** Represents an @{@link org.testng.annotations.DataProvider} annotated method. */ class DataProviderMethodRemovable extends DataProviderMethod { - DataProviderMethodRemovable(Object instance, Method method, IDataProviderAnnotation annotation) { + DataProviderMethodRemovable( + IInstanceInfo instance, Method method, IDataProviderAnnotation annotation) { super(instance, method, annotation); } - public void setInstance(Object instance) { + public void setInstance(IInstanceInfo instance) { this.instance = instance; } diff --git a/testng-core/src/main/java/org/testng/internal/DynamicGraphHelper.java b/testng-core/src/main/java/org/testng/internal/DynamicGraphHelper.java index 91fa7cb55f..1c72327f99 100644 --- a/testng-core/src/main/java/org/testng/internal/DynamicGraphHelper.java +++ b/testng-core/src/main/java/org/testng/internal/DynamicGraphHelper.java @@ -8,6 +8,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import org.testng.DependencyMap; +import org.testng.IInstanceInfo; import org.testng.ITestNGMethod; import org.testng.TestRunner; import org.testng.collections.ListMultiMap; @@ -181,19 +182,19 @@ private static ListMultiMap createClassDependencie private static ListMultiMap createInstanceDependencies( ITestNGMethod[] methods) { - ListMultiMap instanceMap = Maps.newSortedListMultiMap(); + ListMultiMap, ITestNGMethod> instanceMap = Maps.newSortedListMultiMap(); for (ITestNGMethod m : methods) { - instanceMap.put(m.getInstance(), m); + instanceMap.put((IInstanceInfo) m.getInstance(), m); } ListMultiMap result = Maps.newListMultiMap(); - Object previousInstance = null; - for (Map.Entry> es : instanceMap.entrySet()) { + IInstanceInfo previousInstance = null; + for (Map.Entry, List> es : instanceMap.entrySet()) { if (previousInstance == null) { previousInstance = es.getKey(); } else { List previousMethods = instanceMap.get(previousInstance); - Object currentInstance = es.getKey(); + IInstanceInfo currentInstance = es.getKey(); List currentMethods = instanceMap.get(currentInstance); // Make all the methods from the current instance depend on the methods of // the previous instance diff --git a/testng-core/src/main/java/org/testng/internal/FactoryMethod.java b/testng-core/src/main/java/org/testng/internal/FactoryMethod.java index 97c851d388..ca1da259d8 100644 --- a/testng-core/src/main/java/org/testng/internal/FactoryMethod.java +++ b/testng-core/src/main/java/org/testng/internal/FactoryMethod.java @@ -12,6 +12,7 @@ import org.testng.DataProviderHolder; import org.testng.IDataProviderInterceptor; import org.testng.IDataProviderListener; +import org.testng.IFactoryMethod; import org.testng.IInstanceInfo; import org.testng.ITestClassInstance; import org.testng.ITestContext; @@ -31,7 +32,7 @@ public class FactoryMethod extends BaseTestMethod { private final IFactoryAnnotation factoryAnnotation; - private final Object m_instance; + private final IInstanceInfo m_instance; private final ITestContext m_testContext; private String m_factoryCreationFailedMessage = null; private final DataProviderHolder holder; @@ -73,14 +74,14 @@ private void init(Object instance, IAnnotationFinder annotationFinder, Construct // constructor outside of this package. FactoryMethod( ConstructorOrMethod com, - IObject.IdentifiableObject identifiable, + IInstanceInfo iinstance, IAnnotationFinder annotationFinder, ITestContext testContext, ITestObjectFactory objectFactory, DataProviderHolder holder) { - super(objectFactory, com.getName(), com, annotationFinder, identifiable); + super(objectFactory, com.getName(), com, annotationFinder, iinstance); this.holder = holder; - Object instance = IObject.IdentifiableObject.unwrap(identifiable); + Object instance = iinstance == null ? null : iinstance.getInstance(); init(instance, annotationFinder, com); Utils.checkInstanceOrStatic(instance, com.getMethod()); Utils.checkReturnType(com.getMethod(), Object[].class, IInstanceInfo[].class); @@ -183,9 +184,11 @@ public ITestClassInstance[] invoke() { // skipped value continue; } + IFactoryMethod factoryMethod = () -> parameters; ConstructorOrMethod com = getConstructorOrMethod(); if (com.getMethod() != null) { - Object[] testInstances = (Object[]) com.getMethod().invoke(m_instance, parameters); + Object[] testInstances = + (Object[]) com.getMethod().invoke(m_instance.getInstance(), parameters); if (testInstances == null) { testInstances = new Object[] {}; } @@ -201,10 +204,10 @@ public ITestClassInstance[] invoke() { Arrays.stream(testInstances) .map( instance -> - new ParameterInfo( + new ParameterInfo<>( instance, instancePosition, - parameters, + factoryMethod, invocationCounter.getAndIncrement())) .collect(Collectors.toList())); } else { @@ -212,10 +215,10 @@ public ITestClassInstance[] invoke() { int i = index - position; if (i >= 0 && i < testInstances.length) { result.add( - new ParameterInfo( + new ParameterInfo<>( testInstances[i], position, - parameters, + factoryMethod, invocationCounter.getAndIncrement())); } } @@ -225,8 +228,8 @@ public ITestClassInstance[] invoke() { if (indices == null || indices.isEmpty() || indices.contains(position)) { Object instance = m_objectFactory.newInstance(com.getConstructor(), parameters); result.add( - new ParameterInfo( - instance, position, parameters, invocationCounter.getAndIncrement())); + new ParameterInfo<>( + instance, position, factoryMethod, invocationCounter.getAndIncrement())); } position++; } diff --git a/testng-core/src/main/java/org/testng/internal/IInstanceIdentity.java b/testng-core/src/main/java/org/testng/internal/IInstanceIdentity.java deleted file mode 100644 index 9b9efe4942..0000000000 --- a/testng-core/src/main/java/org/testng/internal/IInstanceIdentity.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.testng.internal; - -import java.util.Arrays; -import java.util.Objects; -import java.util.UUID; - -public interface IInstanceIdentity { - - /** - * @return - A {@link UUID} that represents a unique id which is associated with - * every test class object. - */ - UUID getInstanceId(); - - static Object getInstanceId(Object object) { - if (object instanceof IInstanceIdentity) { - return ((IInstanceIdentity) object).getInstanceId(); - } - return object; - } - - /** - * @param objects - The objects to inspect - * @return - true if all the objects passed are of type {@link IInstanceIdentity} - */ - static boolean isIdentityAware(Object... objects) { - return Arrays.stream(Objects.requireNonNull(objects)) - .allMatch(it -> it instanceof IInstanceIdentity); - } -} diff --git a/testng-core/src/main/java/org/testng/internal/IObject.java b/testng-core/src/main/java/org/testng/internal/IObject.java index 4389b6ec00..503395dc48 100644 --- a/testng-core/src/main/java/org/testng/internal/IObject.java +++ b/testng-core/src/main/java/org/testng/internal/IObject.java @@ -1,9 +1,10 @@ package org.testng.internal; import java.util.Arrays; -import java.util.Objects; import java.util.Optional; import java.util.UUID; +import org.testng.IInstanceInfo; +import org.testng.ITestClassInstance; /** * Represents the associations of a class with one or more instances. Relevant with @Factory @@ -18,15 +19,15 @@ public interface IObject { * @param create - true if objects should be created before returning. * @param errorMsgPrefix - Text that should be prefixed to the error message when there are * issues. Can be empty. - * @return - An array of {@link IdentifiableObject} objects + * @return - An array of {@link ITestClassInstance} objects */ - IdentifiableObject[] getObjects(boolean create, String errorMsgPrefix); + IInstanceInfo[] getObjects(boolean create, String errorMsgPrefix); /** @return - An array representing the hash codes of the corresponding instances. */ long[] getInstanceHashCodes(); /** @param instance - The instance that should be added to the list of instances. */ - void addObject(IdentifiableObject instance); + void addObject(IInstanceInfo instance); /** * @param object - The object that should be inspected for its compatibility with {@link IObject}. @@ -39,10 +40,10 @@ static long[] instanceHashCodes(Object object) { /** * @param object - The object that should be inspected for its compatibility with {@link IObject}. * @param create - true if objects should be created before returning. - * @return - An array (can be empty is instance compatibility fails) of {@link IdentifiableObject} + * @return - An array (can be empty is instance compatibility fails) of {@link ITestClassInstance} * objects. */ - static IdentifiableObject[] objects(Object object, boolean create) { + static IInstanceInfo[] objects(Object object, boolean create) { return objects(object, create, ""); } @@ -51,13 +52,13 @@ static IdentifiableObject[] objects(Object object, boolean create) { * @param create - true if objects should be created before returning. * @param errorMsgPrefix - Text that should be prefixed to the error message when there are * issues. Can be empty. - * @return - An array (can be empty is instance compatibility fails) of {@link IdentifiableObject} + * @return - An array (can be empty is instance compatibility fails) of {@link ITestClassInstance} * objects. */ - static IdentifiableObject[] objects(Object object, boolean create, String errorMsgPrefix) { + static IInstanceInfo[] objects(Object object, boolean create, String errorMsgPrefix) { return cast(object) .map(it -> it.getObjects(create, errorMsgPrefix)) - .orElse(new IdentifiableObject[] {}); + .orElse(new ITestClassInstance[0]); } /** @@ -72,49 +73,6 @@ static Optional cast(Object object) { return Optional.empty(); } - /** A wrapper object that associates a unique id to every unique test class object. */ - class IdentifiableObject { - private final Object instance; - private final UUID instanceId; - - public IdentifiableObject(Object instance) { - this(instance, UUID.randomUUID()); - } - - public IdentifiableObject(Object instance, UUID instanceId) { - this.instance = instance; - this.instanceId = instanceId; - } - - public static Object unwrap(IdentifiableObject object) { - if (object == null) { - return null; - } - return object.getInstance(); - } - - public UUID getInstanceId() { - return instanceId; - } - - public Object getInstance() { - return instance; - } - - @Override - public boolean equals(Object object) { - if (this == object) return true; - if (object == null || getClass() != object.getClass()) return false; - IdentifiableObject that = (IdentifiableObject) object; - return Objects.equals(instanceId, that.instanceId); - } - - @Override - public int hashCode() { - return Objects.hash(instanceId); - } - } - /** * A wrapper class that wraps around an array and associates a unique Id that can be used as a key * for the array. diff --git a/testng-core/src/main/java/org/testng/internal/ITestClassConfigInfo.java b/testng-core/src/main/java/org/testng/internal/ITestClassConfigInfo.java index 9001920f91..9afb07827f 100644 --- a/testng-core/src/main/java/org/testng/internal/ITestClassConfigInfo.java +++ b/testng-core/src/main/java/org/testng/internal/ITestClassConfigInfo.java @@ -1,6 +1,7 @@ package org.testng.internal; import java.util.List; +import org.testng.IInstanceInfo; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.collections.Lists; @@ -22,9 +23,9 @@ public interface ITestClassConfigInfo { * @param instance object hashcode * @return All before class methods of instance */ - List getInstanceBeforeClassMethods(Object instance); + List getInstanceBeforeClassMethods(IInstanceInfo instance); - List getInstanceAfterClassMethods(Object instance); + List getInstanceAfterClassMethods(IInstanceInfo instance); static List allBeforeClassMethods(ITestClass tc) { if (tc instanceof ITestClassConfigInfo) { diff --git a/testng-core/src/main/java/org/testng/internal/InstanceInfo.java b/testng-core/src/main/java/org/testng/internal/InstanceInfo.java index 198cfc9c0b..51b55d4655 100644 --- a/testng-core/src/main/java/org/testng/internal/InstanceInfo.java +++ b/testng-core/src/main/java/org/testng/internal/InstanceInfo.java @@ -1,16 +1,28 @@ package org.testng.internal; +import java.util.UUID; import org.testng.IInstanceInfo; public class InstanceInfo implements IInstanceInfo { + private final UUID uuid; private final Class m_instanceClass; private final T m_instance; + public InstanceInfo(T instance) { + this(instance == null ? null : (Class) instance.getClass(), instance); + } + public InstanceInfo(Class cls, T instance) { + uuid = UUID.randomUUID(); m_instanceClass = cls; m_instance = instance; } + @Override + public UUID getUid() { + return uuid; + } + @Override public T getInstance() { return m_instance; diff --git a/testng-core/src/main/java/org/testng/internal/MethodHelper.java b/testng-core/src/main/java/org/testng/internal/MethodHelper.java index fe14680e8f..c48d9c7ae9 100644 --- a/testng-core/src/main/java/org/testng/internal/MethodHelper.java +++ b/testng-core/src/main/java/org/testng/internal/MethodHelper.java @@ -15,6 +15,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.testng.IInstanceInfo; import org.testng.IMethodInstance; import org.testng.ITestClass; import org.testng.ITestNGMethod; @@ -323,7 +324,7 @@ private static Graph topologicalSort( // Create the graph // - Map> testInstances = sortMethodsByInstance(methods); + Map, List> testInstances = sortMethodsByInstance(methods); XmlTest xmlTest = null; @@ -341,7 +342,8 @@ private static Graph topologicalSort( // Method has instance if (m.getInstance() != null) { // Get other methods with the same instance - List instanceMethods = testInstances.get(m.getInstance()); + List instanceMethods = + testInstances.get((IInstanceInfo) m.getInstance()); try { // Search for other methods that depends upon with the same instance methodsNamed = MethodHelper.findDependedUponMethods(m, instanceMethods); @@ -413,11 +415,15 @@ private static boolean isIndependent(ITestNGMethod tm) { * @param methods Methods to be sorted * @return Map of Instances as the keys and the methods associated with the instance as the values */ - private static Map> sortMethodsByInstance(ITestNGMethod[] methods) { + private static Map, List> sortMethodsByInstance( + ITestNGMethod[] methods) { return Arrays.stream(methods) .parallel() .filter(m -> Objects.nonNull(m.getInstance())) - .collect(Collectors.groupingBy(ITestNGMethod::getInstance, Collectors.toList())); + .collect( + Collectors.groupingBy( + (ITestNGMethod iTestNGMethod) -> (IInstanceInfo) iTestNGMethod.getInstance(), + Collectors.toList())); } protected static String calculateMethodCanonicalName(ITestNGMethod m) { diff --git a/testng-core/src/main/java/org/testng/internal/MethodInstance.java b/testng-core/src/main/java/org/testng/internal/MethodInstance.java index e8535ef281..57628195c6 100644 --- a/testng-core/src/main/java/org/testng/internal/MethodInstance.java +++ b/testng-core/src/main/java/org/testng/internal/MethodInstance.java @@ -2,6 +2,7 @@ import java.util.Comparator; import java.util.List; +import org.testng.IInstanceInfo; import org.testng.IMethodInstance; import org.testng.ITestNGMethod; import org.testng.collections.Objects; @@ -22,8 +23,8 @@ public ITestNGMethod getMethod() { } @Override - public Object getInstance() { - return m_method.getInstance(); + public IInstanceInfo getInstance() { + return (IInstanceInfo) m_method.getInstance(); } @Override diff --git a/testng-core/src/main/java/org/testng/internal/MethodSorting.java b/testng-core/src/main/java/org/testng/internal/MethodSorting.java index b7e6e2fe13..092436bd92 100644 --- a/testng-core/src/main/java/org/testng/internal/MethodSorting.java +++ b/testng-core/src/main/java/org/testng/internal/MethodSorting.java @@ -2,10 +2,10 @@ import java.util.Arrays; import java.util.Comparator; -import java.util.Objects; import java.util.Optional; import java.util.UUID; -import org.testng.IFactoryMethod; +import org.testng.IInstanceInfo; +import org.testng.ITestClassInstance; import org.testng.ITestNGMethod; public enum MethodSorting implements Comparator { @@ -31,23 +31,21 @@ public int compare(ITestNGMethod o1, ITestNGMethod o2) { .thenComparing(ITestNGMethod::getMethodName) .thenComparing(Object::toString) .thenComparing( - method -> - method - .getFactoryMethod() - .flatMap(IFactoryMethod::getParameters) - .map(Arrays::toString) - .orElse("")) + method -> { + if (!(method instanceof ITestClassInstance)) { + return ""; + } + return Arrays.toString( + ((ITestClassInstance) method).getFactoryMethod().getParameters()); + }) .thenComparing(this::objectEquality); return comparator.compare(o1, o2); } private int objectEquality(ITestNGMethod a, ITestNGMethod b) { - Object one = IInstanceIdentity.getInstanceId(a.getInstance()); - Object two = IInstanceIdentity.getInstanceId(b.getInstance()); - if (IInstanceIdentity.isIdentityAware(one, two)) { - return ((UUID) one).compareTo((UUID) two); - } - return Integer.compare(Objects.hashCode(one), Objects.hashCode(two)); + UUID one = ((IInstanceInfo) a.getInstance()).getUid(); + UUID two = ((IInstanceInfo) b.getInstance()).getUid(); + return one.compareTo(two); } @Override diff --git a/testng-core/src/main/java/org/testng/internal/NoOpTestClass.java b/testng-core/src/main/java/org/testng/internal/NoOpTestClass.java index bb3feb3bbf..c1984e2746 100644 --- a/testng-core/src/main/java/org/testng/internal/NoOpTestClass.java +++ b/testng-core/src/main/java/org/testng/internal/NoOpTestClass.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import org.testng.IInstanceInfo; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.xml.XmlClass; @@ -24,7 +25,7 @@ public class NoOpTestClass implements ITestClass, IObject { protected ITestNGMethod[] m_beforeGroupsMethods = new ITestNGMethod[0]; protected List m_afterGroupsMethods = new ArrayList<>(); - private final IdentifiableObject[] m_instances; + private final IInstanceInfo[] m_instances; private final long[] m_instanceHashes; private final XmlTest m_xmlTest; @@ -150,10 +151,10 @@ public Class getRealClass() { public void addInstance(Object instance) {} @Override - public void addObject(IdentifiableObject instance) {} + public void addObject(IInstanceInfo instance) {} @Override - public IdentifiableObject[] getObjects(boolean create, String errorMsgPrefix) { + public IInstanceInfo[] getObjects(boolean create, String errorMsgPrefix) { return m_instances; } diff --git a/testng-core/src/main/java/org/testng/internal/ParameterInfo.java b/testng-core/src/main/java/org/testng/internal/ParameterInfo.java index 9a10491dea..1d82947e64 100644 --- a/testng-core/src/main/java/org/testng/internal/ParameterInfo.java +++ b/testng-core/src/main/java/org/testng/internal/ParameterInfo.java @@ -1,21 +1,25 @@ package org.testng.internal; -public class ParameterInfo implements IParameterInfo { - private final Object instance; +import java.util.Arrays; +import org.testng.IFactoryMethod; +import org.testng.ITestClassInstance; + +public class ParameterInfo extends InstanceInfo + implements ITestClassInstance, IParameterInfo { private final int index; - private final Object[] parameters; + private final IFactoryMethod factoryMethod; private final int invocationIndex; - public ParameterInfo(Object instance, int index, Object[] parameters, int invocationIndex) { - this.instance = instance; + public ParameterInfo(T instance, int index, IFactoryMethod factoryMethod, int invocationIndex) { + super(instance); this.index = index; - this.parameters = parameters; + this.factoryMethod = factoryMethod; this.invocationIndex = invocationIndex; } @Override - public Object getInstance() { - return instance; + public Class getInstanceClass() { + return (Class) getInstance().getClass(); } @Override @@ -28,8 +32,18 @@ public int getInvocationIndex() { return invocationIndex; } + @Override + public IFactoryMethod getFactoryMethod() { + return factoryMethod; + } + @Override public Object[] getParameters() { - return parameters; + return factoryMethod.getParameters(); + } + + @Override + public String toString() { + return super.toString() + ", instance params:" + Arrays.toString(factoryMethod.getParameters()); } } diff --git a/testng-core/src/main/java/org/testng/internal/Parameters.java b/testng-core/src/main/java/org/testng/internal/Parameters.java index 14460e2e6e..7a12d6407a 100644 --- a/testng-core/src/main/java/org/testng/internal/Parameters.java +++ b/testng-core/src/main/java/org/testng/internal/Parameters.java @@ -648,9 +648,9 @@ private static IDataProviderMethod findDataProvider( } if (isDynamicDataProvider) { - result = new DataProviderMethodRemovable(instanceToUse, m, dp); + result = new DataProviderMethodRemovable(new InstanceInfo<>(instanceToUse), m, dp); } else { - result = new DataProviderMethod(instanceToUse, m, dp); + result = new DataProviderMethod(new InstanceInfo<>(instanceToUse), m, dp); } } diff --git a/testng-core/src/main/java/org/testng/internal/TestListenerHelper.java b/testng-core/src/main/java/org/testng/internal/TestListenerHelper.java index c585193ab7..03954a6fb0 100644 --- a/testng-core/src/main/java/org/testng/internal/TestListenerHelper.java +++ b/testng-core/src/main/java/org/testng/internal/TestListenerHelper.java @@ -6,6 +6,7 @@ import java.util.Optional; import org.testng.IClass; import org.testng.IConfigurationListener; +import org.testng.IInstanceInfo; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestNGListener; @@ -157,7 +158,7 @@ public static ITestNGListenerFactory createListenerFactory( try { if (finder != null) { IClass ic = finder.getIClass(factoryClass); - IObject.IdentifiableObject[] created = IObject.objects(ic, false); + IInstanceInfo[] created = IObject.objects(ic, false); if (created.length != 0) { listenerFactory = (ITestNGListenerFactory) created[0].getInstance(); } diff --git a/testng-core/src/main/java/org/testng/internal/TestNGClassFinder.java b/testng-core/src/main/java/org/testng/internal/TestNGClassFinder.java index e8b9dfb09d..f692ee8a5c 100644 --- a/testng-core/src/main/java/org/testng/internal/TestNGClassFinder.java +++ b/testng-core/src/main/java/org/testng/internal/TestNGClassFinder.java @@ -6,6 +6,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -21,7 +22,6 @@ import org.testng.annotations.IAnnotation; import org.testng.annotations.IObjectFactoryAnnotation; import org.testng.collections.Lists; -import org.testng.collections.Maps; import org.testng.internal.annotations.AnnotationHelper; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.xml.XmlClass; @@ -35,7 +35,7 @@ public class TestNGClassFinder extends BaseClassFinder { private static final String PREFIX = "[TestNGClassFinder]"; private final ITestContext m_testContext; - private final Map, List> m_instanceMap = Maps.newHashMap(); + private final Map, List>> m_instanceMap = new HashMap<>(); private final DataProviderHolder holder; private final ITestObjectFactory objectFactory; private final IAnnotationFinder annotationFinder; @@ -48,7 +48,7 @@ public String getFactoryCreationFailedMessage() { public TestNGClassFinder( ClassInfoMap cim, - Map, List> instanceMap, + Map, List>> instanceMap, IConfiguration configuration, ITestContext testContext, DataProviderHolder holder) { @@ -72,9 +72,9 @@ public TestNGClassFinder( // // Add all the instances we found to their respective IClasses // - for (Map.Entry, List> entry : m_instanceMap.entrySet()) { + for (Map.Entry, List>> entry : m_instanceMap.entrySet()) { Class clazz = entry.getKey(); - for (IObject.IdentifiableObject instance : entry.getValue()) { + for (IInstanceInfo instance : entry.getValue()) { IClass ic = getIClass(clazz); IObject.cast(ic).ifPresent(it -> it.addObject(instance)); } @@ -83,7 +83,7 @@ public TestNGClassFinder( private void processClass( ClassInfoMap cim, - Map, List> instanceMap, + Map, List>> instanceMap, IConfiguration configuration, Class cls) { if (null == cls) { @@ -95,8 +95,8 @@ private void processClass( Utils.log(PREFIX, 3, "SKIPPING CLASS " + cls + " no TestNG annotations found"); return; } - List allInstances = instanceMap.get(cls); - IObject.IdentifiableObject thisInstance = + List> allInstances = instanceMap.get(cls); + IInstanceInfo thisInstance = (allInstances != null && !allInstances.isEmpty()) ? allInstances.get(0) : null; // If annotation class and instances are abstract, skip them @@ -164,9 +164,9 @@ private static boolean excludeFactory(FactoryMethod fm, ITestContext ctx) { } private ClassInfoMap processFactory(IClass ic, ConstructorOrMethod factoryMethod) { - IObject.IdentifiableObject[] theseInstances = IObject.objects(ic, false); + IInstanceInfo[] theseInstances = IObject.objects(ic, false); - IObject.IdentifiableObject instance = theseInstances.length != 0 ? theseInstances[0] : null; + IInstanceInfo instance = theseInstances.length != 0 ? theseInstances[0] : null; FactoryMethod fm = new FactoryMethod( factoryMethod, instance, annotationFinder, m_testContext, objectFactory, holder); @@ -179,7 +179,7 @@ private ClassInfoMap processFactory(IClass ic, ConstructorOrMethod factoryMethod // If the factory returned IInstanceInfo, get the class from it, // otherwise, just call getClass() on the returned instances int i = 0; - for (ITestClassInstance o : fm.invoke()) { + for (ITestClassInstance o : fm.invoke()) { if (o == null) { throw new TestNGException( "The factory " + fm + " returned a null instance" + "at index " + i); @@ -191,7 +191,7 @@ private ClassInfoMap processFactory(IClass ic, ConstructorOrMethod factoryMethod addInstance(ii); oneMoreClass = ii.getInstanceClass(); } else { - addInstance(new IObject.IdentifiableObject(o)); + addInstance(o); oneMoreClass = objToInspect.getClass(); } if (!classExists(oneMoreClass)) { @@ -325,21 +325,13 @@ private static boolean isTestNGClass(Class c, IAnnotationFinder annotationFin // IInstanceInfo should be replaced by IInstanceInfo but eclipse complains against it. // See: https://github.com/cbeust/testng/issues/1070 private void addInstance(IInstanceInfo ii) { - addInstance(ii.getInstanceClass(), new IObject.IdentifiableObject(ii.getInstance())); - } - - private void addInstance(IObject.IdentifiableObject o) { - Class key = o.getInstance().getClass(); - if (o.getInstance() instanceof ITestClassInstance) { - key = ((ITestClassInstance) o.getInstance()).getInstance().getClass(); - } - addInstance(key, o); + addInstance(ii.getInstanceClass(), ii); } // Class should be replaced by Class but java doesn't fail as expected // See: https://github.com/cbeust/testng/issues/1070 - private void addInstance(Class clazz, IObject.IdentifiableObject instance) { - List instances = + private void addInstance(Class clazz, IInstanceInfo instance) { + List> instances = m_instanceMap.computeIfAbsent(clazz, key -> Lists.newArrayList()); instances.add(instance); } diff --git a/testng-core/src/main/java/org/testng/internal/TestNGMethod.java b/testng-core/src/main/java/org/testng/internal/TestNGMethod.java index eef4e16a69..28ae011a60 100644 --- a/testng-core/src/main/java/org/testng/internal/TestNGMethod.java +++ b/testng-core/src/main/java/org/testng/internal/TestNGMethod.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Objects; import org.testng.IDataProviderMethod; +import org.testng.IInstanceInfo; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.ITestObjectFactory; @@ -33,7 +34,7 @@ public TestNGMethod( Method method, IAnnotationFinder finder, XmlTest xmlTest, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { this(objectFactory, method, finder, true, xmlTest, instance); } @@ -43,7 +44,7 @@ private TestNGMethod( IAnnotationFinder finder, boolean initialize, XmlTest xmlTest, - IObject.IdentifiableObject instance) { + IInstanceInfo instance) { super(objectFactory, method.getName(), new ConstructorOrMethod(method), finder, instance); setXmlTest(xmlTest); @@ -73,9 +74,8 @@ public boolean isTest() { private void init(XmlTest xmlTest) { setXmlTest(xmlTest); String className = m_method.getDeclaringClass().getName(); - Object obj = getInstance(); - if (obj != null) { - className = obj.getClass().getName(); + if (getInstance() != null && getInstance().getInstanceClass() != null) { + className = getInstance().getInstanceClass().getName(); } setInvocationNumbers(xmlTest.getInvocationNumbers(className + "." + m_method.getName())); @@ -171,7 +171,7 @@ public BaseTestMethod clone() { getAnnotationFinder(), false, getXmlTest(), - new IObject.IdentifiableObject(getInstance(), getInstanceId())); + getInstance()); ITestClass tc = getTestClass(); NoOpTestClass testClass = new NoOpTestClass(tc); testClass.setBeforeTestMethods(clone(tc.getBeforeTestMethods())); diff --git a/testng-core/src/main/java/org/testng/internal/WrappedTestNGMethod.java b/testng-core/src/main/java/org/testng/internal/WrappedTestNGMethod.java index 7700d33fb3..755a711b2c 100644 --- a/testng-core/src/main/java/org/testng/internal/WrappedTestNGMethod.java +++ b/testng-core/src/main/java/org/testng/internal/WrappedTestNGMethod.java @@ -3,9 +3,9 @@ import java.util.List; import java.util.Map; import java.util.Random; -import java.util.UUID; import java.util.concurrent.Callable; import org.testng.IClass; +import org.testng.IInstanceInfo; import org.testng.IRetryAnalyzer; import org.testng.ITestClass; import org.testng.ITestNGMethod; @@ -17,18 +17,12 @@ * generates a unique hashcode that is different from the original {@link ITestNGMethod} instance * that it wraps. */ -public class WrappedTestNGMethod implements ITestNGMethod, IInstanceIdentity { +public class WrappedTestNGMethod implements ITestNGMethod { private final ITestNGMethod testNGMethod; private final int multiplicationFactor = new Random().nextInt(); - private final UUID uuid; - public WrappedTestNGMethod(ITestNGMethod testNGMethod) { this.testNGMethod = testNGMethod; - uuid = - (testNGMethod instanceof BaseTestMethod) - ? ((BaseTestMethod) testNGMethod).getInstanceId() - : UUID.randomUUID(); } @Override @@ -52,8 +46,8 @@ public String getMethodName() { } @Override - public Object getInstance() { - return testNGMethod.getInstance(); + public IInstanceInfo getInstance() { + return (IInstanceInfo) testNGMethod.getInstance(); } @Override @@ -371,11 +365,6 @@ public String getQualifiedName() { return testNGMethod.getQualifiedName(); } - @Override - public UUID getInstanceId() { - return uuid; - } - @Override public boolean equals(Object o) { return o == this || (o instanceof ITestNGMethod && testNGMethod.equals(o)); diff --git a/testng-core/src/main/java/org/testng/internal/annotations/JDK15AnnotationFinder.java b/testng-core/src/main/java/org/testng/internal/annotations/JDK15AnnotationFinder.java index 2b1f776e61..694384d007 100644 --- a/testng-core/src/main/java/org/testng/internal/annotations/JDK15AnnotationFinder.java +++ b/testng-core/src/main/java/org/testng/internal/annotations/JDK15AnnotationFinder.java @@ -10,6 +10,7 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import org.testng.IAnnotationTransformer; +import org.testng.IInstanceInfo; import org.testng.ITestNGMethod; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterGroups; @@ -131,7 +132,7 @@ public A findAnnotation(ITestNGMethod tm, Class annot Method m = tm.getConstructorOrMethod().getMethod(); Class testClass = m.getDeclaringClass(); if (tm.getInstance() != null) { - testClass = tm.getInstance().getClass(); + testClass = ((IInstanceInfo) tm.getInstance()).getInstanceClass(); } Annotation annotation = AnnotationHelper.getAnnotationFromMethod(m, a); if (annotation == null) { diff --git a/testng-core/src/main/java/org/testng/internal/invokers/Arguments.java b/testng-core/src/main/java/org/testng/internal/invokers/Arguments.java index 4eb20310b8..11bf4ca999 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/Arguments.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/Arguments.java @@ -1,6 +1,7 @@ package org.testng.internal.invokers; import java.util.Map; +import org.testng.IInstanceInfo; import org.testng.ITestNGMethod; public class Arguments { @@ -10,6 +11,9 @@ public class Arguments { protected final Map params; protected Arguments(Object instance, ITestNGMethod tm, Map params) { + if (instance instanceof IInstanceInfo) { + throw new IllegalArgumentException(); + } this.instance = instance; this.tm = tm; this.params = params; diff --git a/testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java b/testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java index 9973d1510f..e1e216bc3b 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java @@ -15,6 +15,7 @@ import org.testng.IClass; import org.testng.IConfigurable; import org.testng.IConfigurationListener; +import org.testng.IInstanceInfo; import org.testng.IInvokedMethodListener; import org.testng.ISuiteRunnerListener; import org.testng.ITestClass; @@ -249,9 +250,10 @@ public void invokeConfigurations(ConfigMethodArguments arguments) { IConfigurationAnnotation configurationAnnotation = null; try { - Object inst = tm.getInstance(); - if (inst == null) { - inst = arguments.getInstance(); + Object inst = arguments.getInstance(); + IInstanceInfo info = (IInstanceInfo) tm.getInstance(); + if (info != null && info.getInstance() != null) { + inst = info.getInstance(); } Class objectClass = inst.getClass(); ConstructorOrMethod method = tm.getConstructorOrMethod(); diff --git a/testng-core/src/main/java/org/testng/internal/invokers/GroupConfigMethodArguments.java b/testng-core/src/main/java/org/testng/internal/invokers/GroupConfigMethodArguments.java index 53c3fb6c8b..6c3af3b513 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/GroupConfigMethodArguments.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/GroupConfigMethodArguments.java @@ -1,6 +1,7 @@ package org.testng.internal.invokers; import java.util.Map; +import org.testng.IInstanceInfo; import org.testng.ITestNGMethod; import org.testng.internal.ConfigurationGroupMethods; import org.testng.xml.XmlSuite; @@ -49,6 +50,9 @@ public Builder withParameters(Map params) { } public Builder forInstance(Object instance) { + if (instance instanceof IInstanceInfo) { + throw new IllegalArgumentException(); + } this.instance = instance; return this; } diff --git a/testng-core/src/main/java/org/testng/internal/invokers/ITestInvoker.java b/testng-core/src/main/java/org/testng/internal/invokers/ITestInvoker.java index 83cca83215..b9e278829a 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/ITestInvoker.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/ITestInvoker.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import org.testng.IInstanceInfo; import org.testng.IInvokedMethod; import org.testng.ITestContext; import org.testng.ITestNGMethod; @@ -24,7 +25,7 @@ class FailureContext { List invokeTestMethods( ITestNGMethod testMethod, ConfigurationGroupMethods groupMethods, - Object instance, + IInstanceInfo instance, ITestContext context); ITestResult invokeTestMethod( diff --git a/testng-core/src/main/java/org/testng/internal/invokers/InstanceBasedParallelParallelWorker.java b/testng-core/src/main/java/org/testng/internal/invokers/InstanceBasedParallelParallelWorker.java index 116a36eda7..51133b86b0 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/InstanceBasedParallelParallelWorker.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/InstanceBasedParallelParallelWorker.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Map; +import org.testng.IInstanceInfo; import org.testng.IMethodInstance; import org.testng.ITestNGMethod; import org.testng.collections.ListMultiMap; @@ -13,15 +14,15 @@ class InstanceBasedParallelParallelWorker extends AbstractParallelWorker { @Override public List> createWorkers(Arguments arguments) { - ListMultiMap lmm = Maps.newSortedListMultiMap(); + ListMultiMap, ITestNGMethod> lmm = Maps.newSortedListMultiMap(); for (ITestNGMethod m : arguments.getMethods()) { - lmm.put(m.getInstance(), m); + lmm.put((IInstanceInfo) m.getInstance(), m); } List> result = Lists.newArrayList(); IInvoker invoker = arguments.getInvoker(); ITestInvoker testInvoker = invoker.getTestInvoker(); IConfigInvoker configInvoker = invoker.getConfigInvoker(); - for (Map.Entry> es : lmm.entrySet()) { + for (Map.Entry, List> es : lmm.entrySet()) { List methodInstances = MethodHelper.methodsToMethodInstances(es.getValue()); TestMethodWorker tmw = new TestMethodWorker( diff --git a/testng-core/src/main/java/org/testng/internal/invokers/MethodRunner.java b/testng-core/src/main/java/org/testng/internal/invokers/MethodRunner.java index a5ff452de7..e9320b1717 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/MethodRunner.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/MethodRunner.java @@ -18,6 +18,7 @@ import org.testng.ITestResult; import org.testng.collections.CollectionUtils; import org.testng.collections.Lists; +import org.testng.internal.InstanceInfo; import org.testng.internal.ObjectBag; import org.testng.internal.Parameters; import org.testng.internal.invokers.ITestInvoker.FailureContext; @@ -129,7 +130,7 @@ public List runInParallel( arguments.getTestMethod(), parametersIndex, parameterValues, - arguments.getInstance(), + new InstanceInfo<>(arguments.getInstance()), arguments.getParameters(), arguments.getTestClass(), arguments.getBeforeMethods(), diff --git a/testng-core/src/main/java/org/testng/internal/invokers/ParameterHandler.java b/testng-core/src/main/java/org/testng/internal/invokers/ParameterHandler.java index d159db2f06..6d7a57f398 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/ParameterHandler.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/ParameterHandler.java @@ -6,6 +6,7 @@ import java.util.Optional; import org.testng.DataProviderHolder; import org.testng.IDataProviderMethod; +import org.testng.IInstanceInfo; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.ITestObjectFactory; @@ -50,7 +51,7 @@ ParameterBag createParameters( Object fedInstance) { return handleParameters( testMethod, - testMethod.getInstance(), + ((IInstanceInfo) testMethod.getInstance()).getInstance(), allParameterNames, parameters, testContext, @@ -64,6 +65,9 @@ private ParameterBag handleParameters( Map parameters, ITestContext testContext, Object fedInstance) { + if (instance instanceof IInstanceInfo) { + throw new IllegalArgumentException("Expected an instance, but got an IInstanceInfo."); + } XmlSuite suite = testContext.getCurrentXmlTest().getSuite(); try { MethodParameters methodParams = diff --git a/testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java b/testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java index e7ef781766..5e22892d4a 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java @@ -25,12 +25,14 @@ import org.testng.IDataProviderListener; import org.testng.IDataProviderMethod; import org.testng.IHookable; +import org.testng.IInstanceInfo; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.IRetryAnalyzer; import org.testng.ISuite; import org.testng.ISuiteRunnerListener; import org.testng.ITestClass; +import org.testng.ITestClassInstance; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestNGMethod; @@ -94,7 +96,7 @@ public ITestResultNotifier getNotifier() { public List invokeTestMethods( ITestNGMethod testMethod, ConfigurationGroupMethods groupMethods, - Object instance, + IInstanceInfo instance, ITestContext context) { // Potential bug here if the test method was declared on a parent class if (testMethod.getTestClass() == null) { @@ -165,7 +167,7 @@ public List invokeTestMethods( new Builder() .forTestMethod(testMethod) .withGroupConfigMethods(groupMethods) - .forInstance(instance) + .forInstance(instance.getInstance()) .withParameters(parameters) .build(); this.invoker.invokeAfterGroupsConfigurations(args); @@ -190,7 +192,7 @@ public List invokeTestMethods( TestMethodArguments arguments = new TestMethodArguments.Builder() - .usingInstance(instance) + .usingInstance(instance.getInstance()) .forTestMethod(testMethod) .withParameters(parameters) .forTestClass(testClass) @@ -358,7 +360,7 @@ private String checkDependencies(ITestNGMethod testMethod) { if (failuresPresentInUpstreamDependency(testMethod, methods)) { String methodsInfo = Arrays.stream(methods) - .map(tm -> tm.getQualifiedName() + "() on instance " + tm.getInstance().toString()) + .map(tm -> tm.getQualifiedName() + "() on instance " + tm.getInstance()) .collect(Collectors.joining("\n")); return String.format( "Method %s() on instance %s depends on not successfully finished methods \n[%s]", @@ -382,8 +384,8 @@ private List runWorkers( // Invoke @BeforeGroups on the original method (reduce thread contention, // and also solve thread confinement) ITestClass testClass = testMethod.getTestClass(); - IObject.IdentifiableObject[] instances = IObject.objects(testClass, true); - for (IObject.IdentifiableObject instance : instances) { + IInstanceInfo[] instances = IObject.objects(testClass, true); + for (IInstanceInfo instance : instances) { GroupConfigMethodArguments arguments = new GroupConfigMethodArguments.Builder() .forTestMethod(testMethod) @@ -409,13 +411,13 @@ private List runWorkers( .flatMap(tmw -> ((TestMethodWorker) tmw).getTestResults().stream()) .collect(Collectors.toList()); - for (Object instance : instances) { + for (IInstanceInfo instance : instances) { GroupConfigMethodArguments arguments = new GroupConfigMethodArguments.Builder() .forTestMethod(testMethod) .withGroupConfigMethods(groupMethods) .withParameters(parameters) - .forInstance(instance) + .forInstance(instance.getInstance()) .build(); invoker.invokeAfterGroupsConfigurations(arguments); } @@ -456,17 +458,19 @@ private Set keepSameInstances(ITestNGMethod method, Set { Object instance = - Optional.ofNullable(r.getInstance()).orElse(r.getMethod().getInstance()); + Optional.ofNullable(r.getInstance()) + .orElse(((IInstanceInfo) r.getMethod().getInstance()).getInstance()); if (method.getGroupsDependedUpon().length == 0) { // Consider equality of objects alone if we are NOT dealing with group dependency. - return instance == method.getInstance(); + return instance == ((IInstanceInfo) method.getInstance()).getInstance(); } // Keep this instance if // 1) It's on a different class or // 2) It's on the same class and on the same instance boolean unEqualTestClasses = !r.getTestClass().getRealClass().equals(method.getTestClass().getRealClass()); - boolean sameInstance = instance == method.getInstance(); + boolean sameInstance = + instance == ((IInstanceInfo) method.getInstance()).getInstance(); return sameInstance || unEqualTestClasses; }) .collect(Collectors.toSet()); @@ -760,8 +764,9 @@ private ITestResult invokeMethod( && (arguments.getParameterValues().length > 0 || testResult.getFactoryParameters().length > 0)) { int parametersIndex = arguments.getParametersIndex(); - if (null != testResult.getMethod().getFactoryMethodParamsInfo()) { - parametersIndex = testResult.getMethod().getFactoryMethodParamsInfo().getIndex(); + if (testResult.getMethod().getInstance() instanceof ITestClassInstance) { + parametersIndex = + ((ITestClassInstance) testResult.getMethod().getInstance()).getIndex(); } arguments.getTestMethod().addFailedInvocationNumber(parametersIndex); } diff --git a/testng-core/src/main/java/org/testng/internal/invokers/TestMethodWithDataProviderMethodWorker.java b/testng-core/src/main/java/org/testng/internal/invokers/TestMethodWithDataProviderMethodWorker.java index 630905b937..28186b2f47 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/TestMethodWithDataProviderMethodWorker.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/TestMethodWithDataProviderMethodWorker.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Callable; +import org.testng.IInstanceInfo; import org.testng.ITestClass; import org.testng.ITestContext; import org.testng.ITestNGMethod; @@ -19,7 +20,7 @@ public class TestMethodWithDataProviderMethodWorker private final ITestNGMethod m_testMethod; private final Object[] m_parameterValues; - private final Object m_instance; + private final IInstanceInfo m_instance; private final Map m_parameters; private final ITestClass m_testClass; private final ITestNGMethod[] m_beforeMethods; @@ -40,7 +41,7 @@ public TestMethodWithDataProviderMethodWorker( ITestNGMethod testMethod, int parameterIndex, Object[] parameterValues, - Object instance, + IInstanceInfo instance, Map parameters, ITestClass testClass, ITestNGMethod[] beforeMethods, @@ -80,7 +81,7 @@ public List call() { tmpResults.add( m_testInvoker.invokeTestMethod( new Builder() - .usingInstance(m_instance) + .usingInstance(m_instance.getInstance()) .forTestMethod(m_testMethod) .withParameterValues(m_parameterValues) .withParametersIndex(m_parameterIndex) diff --git a/testng-core/src/main/java/org/testng/internal/invokers/TestMethodWorker.java b/testng-core/src/main/java/org/testng/internal/invokers/TestMethodWorker.java index 0cf80c1fdc..55cbd9b563 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/TestMethodWorker.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/TestMethodWorker.java @@ -8,9 +8,11 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.UUID; import javax.annotation.Nonnull; import org.testng.ClassMethodMap; import org.testng.IClassListener; +import org.testng.IInstanceInfo; import org.testng.IMethodInstance; import org.testng.ITestClass; import org.testng.ITestContext; @@ -122,7 +124,8 @@ && doesTaskHavePreRequisites() for (IMethodInstance testMethodInstance : m_methodInstances) { ITestNGMethod testMethod = testMethodInstance.getMethod(); - Object key = Objects.requireNonNull(IInstanceIdentity.getInstanceId(testMethod)); + UUID key = + Objects.requireNonNull(((IInstanceInfo) testMethodInstance.getInstance()).getUid()); if (canInvokeBeforeClassMethods()) { try (KeyAwareAutoCloseableLock.AutoReleasable ignored = lock.lockForObject(key)) { invokeBeforeClassMethods(testMethod.getTestClass(), testMethodInstance); @@ -131,7 +134,7 @@ && doesTaskHavePreRequisites() // Invoke test method try { - invokeTestMethods(testMethod, testMethod.getInstance()); + invokeTestMethods(testMethod, (IInstanceInfo) testMethodInstance.getInstance()); } finally { try (KeyAwareAutoCloseableLock.AutoReleasable ignored = lock.lockForObject(key)) { invokeAfterClassMethods(testMethod.getTestClass(), testMethodInstance); @@ -144,7 +147,7 @@ private boolean doesTaskHavePreRequisites() { return threadIdToRunOn != -1; } - protected void invokeTestMethods(ITestNGMethod tm, Object instance) { + protected void invokeTestMethods(ITestNGMethod tm, IInstanceInfo instance) { // Potential bug here: we look up the method index of tm among all // the test methods (not very efficient) but if this method appears // several times and these methods are run in parallel, the results @@ -164,11 +167,11 @@ private boolean canInvokeBeforeClassMethods() { /** Invoke the @BeforeClass methods if not done already */ protected void invokeBeforeClassMethods(ITestClass testClass, IMethodInstance mi) { - Map> invokedBeforeClassMethods = + Map>> invokedBeforeClassMethods = m_classMethodMap.getInvokedBeforeClassMethods(); - Set instances = + Set> instances = invokedBeforeClassMethods.computeIfAbsent(testClass, key -> Sets.newConcurrentHashSet()); - Object instance = mi.getInstance(); + IInstanceInfo instance = (IInstanceInfo) mi.getInstance(); if (!instances.contains(instance)) { instances.add(instance); List original = @@ -183,7 +186,7 @@ protected void invokeBeforeClassMethods(ITestClass testClass, IMethodInstance mi ((ITestClassConfigInfo) testClass).getInstanceBeforeClassMethods(instance)) .forSuite(m_testContext.getSuite().getXmlSuite()) .usingParameters(m_parameters) - .usingInstance(instance) + .usingInstance(instance.getInstance()) .build(); m_configInvoker.invokeConfigurations(attributes); } @@ -200,17 +203,18 @@ protected void invokeAfterClassMethods(ITestClass testClass, IMethodInstance mi) // // Invoke after class methods if this test method is the last one // - List invokeInstances = Lists.newArrayList(); + List> invokeInstances = Lists.newArrayList(); ITestNGMethod tm = mi.getMethod(); - boolean removalSuccessful = m_classMethodMap.removeAndCheckIfLast(tm, mi.getInstance()); + boolean removalSuccessful = + m_classMethodMap.removeAndCheckIfLast(tm, (IInstanceInfo) mi.getInstance()); if (!removalSuccessful) { return; } - Map> invokedAfterClassMethods = + Map>> invokedAfterClassMethods = m_classMethodMap.getInvokedAfterClassMethods(); - Set instances = + Set> instances = invokedAfterClassMethods.computeIfAbsent(testClass, key -> Sets.newHashSet()); - Object inst = mi.getInstance(); + IInstanceInfo inst = (IInstanceInfo) mi.getInstance(); if (!instances.contains(inst)) { invokeInstances.add(inst); } @@ -224,14 +228,15 @@ protected void invokeAfterClassMethods(ITestClass testClass, IMethodInstance mi) } } - private void invokeAfterClassConfigurations(ITestClass testClass, List invokeInstances) { - for (Object invokeInstance : invokeInstances) { + private void invokeAfterClassConfigurations( + ITestClass testClass, List> invokeInstances) { + for (IInstanceInfo invokeInstance : invokeInstances) { ConfigMethodArguments attributes = new Builder() .forTestClass(testClass) .forSuite(m_testContext.getSuite().getXmlSuite()) .usingParameters(m_parameters) - .usingInstance(invokeInstance) + .usingInstance(invokeInstance.getInstance()) .usingConfigMethodsAs( ((ITestClassConfigInfo) testClass).getInstanceAfterClassMethods(invokeInstance)) .build(); diff --git a/testng-core/src/main/java/org/testng/internal/invokers/TestNgMethodUtils.java b/testng-core/src/main/java/org/testng/internal/invokers/TestNgMethodUtils.java index 82cae96c63..ab2bc0440c 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/TestNgMethodUtils.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/TestNgMethodUtils.java @@ -5,6 +5,7 @@ import java.util.Optional; import java.util.function.BiPredicate; import org.testng.IClass; +import org.testng.IInstanceInfo; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.collections.Lists; @@ -105,7 +106,10 @@ private static boolean isSameInstance(ITestNGMethod tm, Object instance) { if (instance == null) { return true; } - Object tmObject = Optional.ofNullable(tm).map(ITestNGMethod::getInstance).orElse(new Object()); + Object tmObject = + Optional.ofNullable(tm) + .map(iTestNGMethod -> ((IInstanceInfo) iTestNGMethod.getInstance()).getInstance()) + .orElse(null); return instance.equals(tmObject); } diff --git a/testng-core/src/main/java/org/testng/internal/objects/SimpleObjectDispenser.java b/testng-core/src/main/java/org/testng/internal/objects/SimpleObjectDispenser.java index 19faf6dc26..bc1d332bce 100644 --- a/testng-core/src/main/java/org/testng/internal/objects/SimpleObjectDispenser.java +++ b/testng-core/src/main/java/org/testng/internal/objects/SimpleObjectDispenser.java @@ -4,6 +4,7 @@ import java.lang.reflect.Modifier; import java.util.Map; import org.testng.IClass; +import org.testng.IInstanceInfo; import org.testng.ITestObjectFactory; import org.testng.TestNGException; import org.testng.annotations.IFactoryAnnotation; @@ -188,7 +189,7 @@ private static Object computeParameters( if (enclosingIClass == null) { return factory.newInstance(ec); } - IObject.IdentifiableObject[] enclosingInstances = IObject.objects(enclosingIClass, false); + IInstanceInfo[] enclosingInstances = IObject.objects(enclosingIClass, false); if (enclosingInstances.length == 0) { return factory.newInstance(ec.getConstructor(ec)); } diff --git a/testng-core/src/main/java/org/testng/reporters/FailedReporter.java b/testng-core/src/main/java/org/testng/reporters/FailedReporter.java index 068af38082..6e5a565f87 100644 --- a/testng-core/src/main/java/org/testng/reporters/FailedReporter.java +++ b/testng-core/src/main/java/org/testng/reporters/FailedReporter.java @@ -11,6 +11,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.testng.IInstanceInfo; import org.testng.IReporter; import org.testng.ISuite; import org.testng.ISuiteResult; @@ -190,8 +191,11 @@ private static void getAllGroupApplicableConfigs( .filter( method -> context.getPassedTests().getAllMethods().stream() - .map(ITestNGMethod::getInstance) - .noneMatch(i -> i.equals(method.getInstance()))) + .map( + iTestNGMethod -> + ((IInstanceInfo) iTestNGMethod.getInstance()).getInstance()) + .noneMatch( + i -> i.equals(((IInstanceInfo) method.getInstance()).getInstance()))) .filter( method -> Arrays.stream(m.getGroups()) @@ -224,8 +228,8 @@ private List createXmlClasses(List methods, XmlTest src Map, Set> methodsMap = Maps.newHashMap(); for (ITestNGMethod m : methods) { - Object instances = m.getInstance(); - Class clazz = instances == null ? m.getRealClass() : instances.getClass(); + IInstanceInfo instance = (IInstanceInfo) m.getInstance(); + Class clazz = instance == null ? m.getRealClass() : instance.getInstanceClass(); Set methodList = methodsMap.computeIfAbsent(clazz, k -> Sets.newHashSet()); methodList.add(m); } diff --git a/testng-core/src/test/java/org/testng/internal/DynamicGraphHelperTest.java b/testng-core/src/test/java/org/testng/internal/DynamicGraphHelperTest.java index 5b94ea28ab..5fdbf52c3b 100644 --- a/testng-core/src/test/java/org/testng/internal/DynamicGraphHelperTest.java +++ b/testng-core/src/test/java/org/testng/internal/DynamicGraphHelperTest.java @@ -110,7 +110,7 @@ public void testCreateDynamicGraphWithGroupByInstances() { objects.add(new FactoryTestClassSample("two")); for (FactoryTestClassSample object : objects) { for (ITestNGMethod method : methods) { - methodList.add(new FakeWrappedFactoryMethod(method, object)); + methodList.add(new FakeWrappedFactoryMethod(method, new InstanceInfo<>(object))); } } ITestNGMethod[] allMethods = methodList.toArray(new ITestNGMethod[0]); @@ -233,7 +233,7 @@ private static List associateInstanceToMethods( each.getConstructorOrMethod().getMethod(), finder, xmlTest, - new IObject.IdentifiableObject(object)); + new InstanceInfo<>(object)); fixedMethods.add(m); } } diff --git a/testng-core/src/test/java/org/testng/internal/MethodHelperTest.java b/testng-core/src/test/java/org/testng/internal/MethodHelperTest.java index 87f46d0932..3995477f3b 100644 --- a/testng-core/src/test/java/org/testng/internal/MethodHelperTest.java +++ b/testng-core/src/test/java/org/testng/internal/MethodHelperTest.java @@ -36,7 +36,7 @@ public void findDependedUponMethods() throws NoSuchMethodException { new String[0], new String[0], Reporter.getCurrentTestResult().getTestContext().getCurrentXmlTest(), - new IObject.IdentifiableObject(testClass)); + new InstanceInfo<>(testClass)); method.addMethodDependedUpon("dummyDependsOnMethod"); ITestNGMethod[] methods = new ITestNGMethod[0]; diff --git a/testng-core/src/test/java/org/testng/internal/MethodInstanceTest.java b/testng-core/src/test/java/org/testng/internal/MethodInstanceTest.java index bcd0840e27..971e90d7be 100644 --- a/testng-core/src/test/java/org/testng/internal/MethodInstanceTest.java +++ b/testng-core/src/test/java/org/testng/internal/MethodInstanceTest.java @@ -7,6 +7,7 @@ import java.util.concurrent.Callable; import org.testng.Assert; import org.testng.IClass; +import org.testng.IInstanceInfo; import org.testng.IRetryAnalyzer; import org.testng.ITestClass; import org.testng.ITestNGMethod; @@ -165,7 +166,7 @@ public Class getRealClass() { public void addInstance(Object instance) {} @Override - public void addObject(IObject.IdentifiableObject instance) { + public void addObject(IInstanceInfo instance) { // Intentionally left blank } @@ -175,8 +176,8 @@ public Object[] getInstances(boolean reuse) { } @Override - public IObject.IdentifiableObject[] getObjects(boolean create, String errorMsgPrefix) { - return new IObject.IdentifiableObject[0]; + public IInstanceInfo[] getObjects(boolean create, String errorMsgPrefix) { + return new IInstanceInfo[0]; } @Override diff --git a/testng-core/src/test/java/org/testng/internal/dynamicgraph/FakeTestClass.java b/testng-core/src/test/java/org/testng/internal/dynamicgraph/FakeTestClass.java index 6ceef4e236..9212311f29 100644 --- a/testng-core/src/test/java/org/testng/internal/dynamicgraph/FakeTestClass.java +++ b/testng-core/src/test/java/org/testng/internal/dynamicgraph/FakeTestClass.java @@ -1,5 +1,6 @@ package org.testng.internal.dynamicgraph; +import org.testng.IInstanceInfo; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.internal.IObject; @@ -99,8 +100,8 @@ public Object[] getInstances(boolean create) { } @Override - public IObject.IdentifiableObject[] getObjects(boolean create, String errorMsgPrefix) { - return new IObject.IdentifiableObject[0]; + public IInstanceInfo[] getObjects(boolean create, String errorMsgPrefix) { + return new IInstanceInfo[0]; } @Override @@ -112,5 +113,5 @@ public long[] getInstanceHashCodes() { public void addInstance(Object instance) {} @Override - public void addObject(IObject.IdentifiableObject instance) {} + public void addObject(IInstanceInfo instance) {} } diff --git a/testng-core/src/test/java/org/testng/internal/dynamicgraph/FakeWrappedFactoryMethod.java b/testng-core/src/test/java/org/testng/internal/dynamicgraph/FakeWrappedFactoryMethod.java index 38db8b2e8c..3f229269c2 100644 --- a/testng-core/src/test/java/org/testng/internal/dynamicgraph/FakeWrappedFactoryMethod.java +++ b/testng-core/src/test/java/org/testng/internal/dynamicgraph/FakeWrappedFactoryMethod.java @@ -1,19 +1,21 @@ package org.testng.internal.dynamicgraph; +import org.testng.IInstanceInfo; import org.testng.ITestNGMethod; +import org.testng.internal.InstanceInfo; import org.testng.internal.WrappedTestNGMethod; public class FakeWrappedFactoryMethod extends WrappedTestNGMethod { - private final Object instance; + private final IInstanceInfo instance; - public FakeWrappedFactoryMethod(ITestNGMethod testNGMethod, Object instance) { + public FakeWrappedFactoryMethod(ITestNGMethod testNGMethod, InstanceInfo instance) { super(testNGMethod); this.instance = instance; } @Override - public Object getInstance() { + public IInstanceInfo getInstance() { return instance; } } diff --git a/testng-core/src/test/java/org/testng/internal/objects/GuiceHelperTest.java b/testng-core/src/test/java/org/testng/internal/objects/GuiceHelperTest.java index eaf22649dc..0fff71ea33 100644 --- a/testng-core/src/test/java/org/testng/internal/objects/GuiceHelperTest.java +++ b/testng-core/src/test/java/org/testng/internal/objects/GuiceHelperTest.java @@ -15,6 +15,7 @@ import org.testng.annotations.Guice; import org.testng.annotations.Test; import org.testng.internal.ClassImpl; +import org.testng.internal.InstanceInfo; import org.testng.internal.paramhandler.FakeTestContext; import test.guice.FakeInjector; @@ -61,7 +62,7 @@ public MockClass() { new FakeTestContext(), GuiceHelperTest.class, null, - new IdentifiableObject((ITest) () -> "GITHUB-2273"), + new InstanceInfo<>((ITest) () -> "GITHUB-2273"), null, null, new ITestObjectFactory() {}); diff --git a/testng-core/src/test/java/org/testng/internal/paramhandler/FakeTestNGMethod.java b/testng-core/src/test/java/org/testng/internal/paramhandler/FakeTestNGMethod.java index e98e6e6fca..e3ac16787b 100644 --- a/testng-core/src/test/java/org/testng/internal/paramhandler/FakeTestNGMethod.java +++ b/testng-core/src/test/java/org/testng/internal/paramhandler/FakeTestNGMethod.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.concurrent.Callable; import org.testng.IClass; +import org.testng.IInstanceInfo; import org.testng.IRetryAnalyzer; import org.testng.ITestClass; import org.testng.ITestNGMethod; @@ -58,7 +59,7 @@ public String getMethodName() { } @Override - public Object getInstance() { + public IInstanceInfo getInstance() { return null; } diff --git a/testng-core/src/test/java/test/configuration/issue2426/MyMethodListener.java b/testng-core/src/test/java/test/configuration/issue2426/MyMethodListener.java index a123f8405c..8438f5d8df 100644 --- a/testng-core/src/test/java/test/configuration/issue2426/MyMethodListener.java +++ b/testng-core/src/test/java/test/configuration/issue2426/MyMethodListener.java @@ -3,7 +3,7 @@ import java.util.HashMap; import java.util.Map; import org.testng.IConfigurationListener; -import org.testng.IFactoryMethod; +import org.testng.ITestClassInstance; import org.testng.ITestResult; import org.testng.annotations.*; @@ -13,11 +13,11 @@ public class MyMethodListener implements IConfigurationListener { @Override public void onConfigurationSuccess(ITestResult tr) { - Object[] values = - tr.getMethod() - .getFactoryMethod() - .flatMap(IFactoryMethod::getParameters) - .orElse(new Object[0]); + Object[] values = new Object[0]; + if (tr.getMethod().getInstance() instanceof ITestClassInstance) { + values = + ((ITestClassInstance) tr.getMethod().getInstance()).getFactoryMethod().getParameters(); + } if (tr.getMethod().isBeforeSuiteConfiguration()) { contents.put(BeforeSuite.class, values); } diff --git a/testng-core/src/test/java/test/dataprovider/DataProviderTest.java b/testng-core/src/test/java/test/dataprovider/DataProviderTest.java index 080dfc67e0..ba88a5f283 100644 --- a/testng-core/src/test/java/test/dataprovider/DataProviderTest.java +++ b/testng-core/src/test/java/test/dataprovider/DataProviderTest.java @@ -10,6 +10,7 @@ import org.assertj.core.api.SoftAssertions; import org.testng.Assert; import org.testng.IDataProviderMethod; +import org.testng.IInstanceInfo; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.TestListenerAdapter; @@ -562,7 +563,8 @@ public void extractDataProviderInfoWhenDpResidesInSameClass( IDataProviderMethod dpm = method.getDataProviderMethod(); assertThat(dpm).isNotNull(); if (performInstanceCheck) { - assertThat(dpm.getInstance()).isEqualTo(method.getInstance()); + assertThat(dpm.getInstance()) + .isEqualTo(((IInstanceInfo) method.getInstance()).getInstance()); } assertThat(dpm.getMethod().getName()).isEqualTo("getData"); assertThat(dpm.getInstance().getClass()).isEqualTo(dataProviderClass); diff --git a/testng-core/src/test/java/test/factory/FactoryIntegrationTest.java b/testng-core/src/test/java/test/factory/FactoryIntegrationTest.java index 76ff2ed763..3d29735272 100644 --- a/testng-core/src/test/java/test/factory/FactoryIntegrationTest.java +++ b/testng-core/src/test/java/test/factory/FactoryIntegrationTest.java @@ -82,13 +82,15 @@ public void doubleFactoryMethodShouldWork() { @Test(dataProvider = "testdata", description = "GITHUB-3111") public void ensureCurrentIndexWorksForFactoryPoweredTests(Class klass, Integer[] expected) { - List params = new ArrayList<>(); + List> params = new ArrayList<>(); TestNG testng = create(klass); testng.addListener( new ITestListener() { @Override public void onTestSuccess(ITestResult result) { - params.add(result.getMethod().getFactoryMethodParamsInfo()); + if (result.getMethod().getInstance() instanceof ITestClassInstance) { + params.add(((ITestClassInstance) result.getMethod().getInstance())); + } } }); testng.run(); diff --git a/testng-core/src/test/java/test/factory/ObjectIdTest.java b/testng-core/src/test/java/test/factory/ObjectIdTest.java index e530e292e2..8d31214594 100644 --- a/testng-core/src/test/java/test/factory/ObjectIdTest.java +++ b/testng-core/src/test/java/test/factory/ObjectIdTest.java @@ -6,6 +6,7 @@ import java.util.Set; import java.util.UUID; import org.assertj.core.api.SoftAssertions; +import org.testng.IInstanceInfo; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; @@ -32,7 +33,7 @@ public void ensureOnlyOneObjectIdExistsForFactoryPoweredTestClass() { TestNG testng = create(FactoryTestCase.class); testng.setParallel(XmlSuite.ParallelMode.INSTANCES); testng.run(); - Map> objectMap = FactoryTestCase.objectMap; + Map>> objectMap = FactoryTestCase.objectMap; assertThat(objectMap.keySet()).hasSize(100); SoftAssertions assertions = new SoftAssertions(); objectMap.forEach((key, value) -> assertions.assertThat(value).hasSize(1)); diff --git a/testng-core/src/test/java/test/factory/issue3079/FactoryTestCase.java b/testng-core/src/test/java/test/factory/issue3079/FactoryTestCase.java index 7996b96276..1e79342bf0 100644 --- a/testng-core/src/test/java/test/factory/issue3079/FactoryTestCase.java +++ b/testng-core/src/test/java/test/factory/issue3079/FactoryTestCase.java @@ -5,7 +5,7 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.IntStream; -import org.testng.ITestNGMethod; +import org.testng.IInstanceInfo; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.annotations.AfterClass; @@ -15,11 +15,10 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; -import org.testng.internal.IInstanceIdentity; public class FactoryTestCase { - public static Map> objectMap = new ConcurrentHashMap<>(); + public static Map>> objectMap = new ConcurrentHashMap<>(); @Factory(dataProvider = "dp") public FactoryTestCase(int ignored) {} @@ -59,10 +58,7 @@ public void afterClass() { private static void record() { ITestResult itr = Reporter.getCurrentTestResult(); - ITestNGMethod itm = itr.getMethod(); - objectMap - .computeIfAbsent( - (UUID) IInstanceIdentity.getInstanceId(itm), k -> ConcurrentHashMap.newKeySet()) - .add(itm.getInstance()); + IInstanceInfo instance = (IInstanceInfo) itr.getMethod().getInstance(); + objectMap.computeIfAbsent(instance.getUid(), k -> ConcurrentHashMap.newKeySet()).add(instance); } } diff --git a/testng-core/src/test/java/test/factory/issue3079/SampleTestCase.java b/testng-core/src/test/java/test/factory/issue3079/SampleTestCase.java index 05ab5a6ad7..58817cc393 100644 --- a/testng-core/src/test/java/test/factory/issue3079/SampleTestCase.java +++ b/testng-core/src/test/java/test/factory/issue3079/SampleTestCase.java @@ -4,7 +4,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -import org.testng.ITestNGMethod; +import org.testng.IInstanceInfo; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.annotations.AfterClass; @@ -13,7 +13,6 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import org.testng.internal.IInstanceIdentity; public class SampleTestCase { public static Map> objectMap = new ConcurrentHashMap<>(); @@ -60,10 +59,7 @@ public void afterClass() { private static void record() { ITestResult itr = Reporter.getCurrentTestResult(); - ITestNGMethod itm = itr.getMethod(); - objectMap - .computeIfAbsent( - (UUID) IInstanceIdentity.getInstanceId(itm), k -> ConcurrentHashMap.newKeySet()) - .add(itm.getInstance()); + IInstanceInfo instance = (IInstanceInfo) itr.getMethod().getInstance(); + objectMap.computeIfAbsent(instance.getUid(), k -> ConcurrentHashMap.newKeySet()).add(instance); } } diff --git a/testng-core/src/test/java/test/listeners/github1490/LocalDataProviderListener.java b/testng-core/src/test/java/test/listeners/github1490/LocalDataProviderListener.java index 695d5a94b1..9fe561946c 100644 --- a/testng-core/src/test/java/test/listeners/github1490/LocalDataProviderListener.java +++ b/testng-core/src/test/java/test/listeners/github1490/LocalDataProviderListener.java @@ -3,6 +3,7 @@ import java.util.List; import org.testng.IDataProviderListener; import org.testng.IDataProviderMethod; +import org.testng.IInstanceInfo; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.collections.Lists; @@ -25,7 +26,10 @@ public void afterDataProviderExecution( private static void log(ITestNGMethod method, String prefix) { if (method.getInstance() != null) { messages.add( - prefix + method.getInstance().getClass().getName() + "." + method.getMethodName()); + prefix + + ((IInstanceInfo) method.getInstance()).getInstanceClass().getName() + + "." + + method.getMethodName()); } else { messages.add(prefix + method.getMethodName()); } diff --git a/testng-core/src/test/java/test/listeners/issue3082/ObjectTrackingMethodListener.java b/testng-core/src/test/java/test/listeners/issue3082/ObjectTrackingMethodListener.java index 1419ba4b06..6a93b2490a 100644 --- a/testng-core/src/test/java/test/listeners/issue3082/ObjectTrackingMethodListener.java +++ b/testng-core/src/test/java/test/listeners/issue3082/ObjectTrackingMethodListener.java @@ -1,5 +1,6 @@ package test.listeners.issue3082; +import org.testng.IInstanceInfo; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.ITestResult; @@ -9,9 +10,9 @@ public class ObjectTrackingMethodListener implements IInvokedMethodListener { @Override public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { String methodName = method.getTestMethod().getMethodName(); - Object instance = method.getTestMethod().getInstance(); - if (instance instanceof IUniqueObject) { - ObjectRepository.add(((IUniqueObject) instance).id(), methodName); + IInstanceInfo instance = (IInstanceInfo) method.getTestMethod().getInstance(); + if (instance.getInstance() instanceof IUniqueObject) { + ObjectRepository.add(((IUniqueObject) instance.getInstance()).id(), methodName); } } } diff --git a/testng-core/src/test/java/test/testng1396/ParallelByInstancesInterceptorTest.java b/testng-core/src/test/java/test/testng1396/ParallelByInstancesInterceptorTest.java index 7391983f00..6cba4a5593 100644 --- a/testng-core/src/test/java/test/testng1396/ParallelByInstancesInterceptorTest.java +++ b/testng-core/src/test/java/test/testng1396/ParallelByInstancesInterceptorTest.java @@ -4,6 +4,7 @@ import java.util.Comparator; import java.util.List; +import org.testng.IInstanceInfo; import org.testng.IMethodInstance; import org.testng.IMethodInterceptor; import org.testng.ITestContext; @@ -69,11 +70,17 @@ public void should_honor_interceptor_order_when_running_parallel_instances() { } private static boolean isHighPriority(IMethodInstance instance) { - return instance.getInstance().getClass().getAnnotation(TestNG1396HighPriority.class) != null; + return ((IInstanceInfo) instance.getInstance()) + .getInstanceClass() + .getAnnotation(TestNG1396HighPriority.class) + != null; } private static boolean isHighPriority(ITestNGMethod method) { - return method.getInstance().getClass().getAnnotation(TestNG1396HighPriority.class) != null; + return ((IInstanceInfo) method.getInstance()) + .getInstanceClass() + .getAnnotation(TestNG1396HighPriority.class) + != null; } public class ReverseOrderTestInterceptor implements IMethodInterceptor { diff --git a/testng-core/src/test/java/test/thread/issue188/IssueTest.java b/testng-core/src/test/java/test/thread/issue188/IssueTest.java index 90104ac2a0..9809f3db2e 100644 --- a/testng-core/src/test/java/test/thread/issue188/IssueTest.java +++ b/testng-core/src/test/java/test/thread/issue188/IssueTest.java @@ -12,6 +12,8 @@ import org.testng.xml.XmlSuite; import test.SimpleBaseTest; +import static org.assertj.core.api.Assertions.assertThat; + public class IssueTest extends SimpleBaseTest { @Test @@ -30,7 +32,7 @@ public void testSuiteLevelParallelMode() { testng.run(); Set timestamps = Issue188TestSample.timestamps.keySet(); if (timestamps.size() == 1) { - Assertions.assertThat(Issue188TestSample.timestamps.values().iterator().next()) + assertThat(Issue188TestSample.timestamps.values().iterator().next()) .withFailMessage( "Since all tests were started simultaneously,test method count should have been 6") .hasSize(6); @@ -39,12 +41,13 @@ public void testSuiteLevelParallelMode() { Issue188TestSample.timestamps.keySet().stream().sorted().collect(Collectors.toList()); String allTimeStamps = keyset.stream().map(Objects::toString).collect(Collectors.joining(",")); + assertThat(keyset).isNotEmpty(); long prev = keyset.get(0); int permissibleLag = 40; for (int i = 1; i < keyset.size(); i++) { long current = keyset.get(i); long diff = current - prev; - Assertions.assertThat(diff) + assertThat(diff) .withFailMessage( "Test methods should have started within a lag of max " + permissibleLag diff --git a/testng-core/src/test/java/test/thread/parallelization/TestNgRunStateListener.java b/testng-core/src/test/java/test/thread/parallelization/TestNgRunStateListener.java index 04327e6fc9..fbc5418359 100644 --- a/testng-core/src/test/java/test/thread/parallelization/TestNgRunStateListener.java +++ b/testng-core/src/test/java/test/thread/parallelization/TestNgRunStateListener.java @@ -20,6 +20,7 @@ import static test.thread.parallelization.TestNgRunStateTracker.logEvent; import java.util.concurrent.TimeUnit; +import org.testng.IInstanceInfo; import org.testng.ISuite; import org.testng.ISuiteListener; import org.testng.ITestContext; @@ -105,7 +106,8 @@ private TestNgRunStateTracker.EventLogBuilder buildEventLog( return (buildEventLog(result.getTestContext(), event)) .addData(METHOD_NAME, result.getMethod().getMethodName()) .addData(CLASS_NAME, result.getMethod().getRealClass().getCanonicalName()) - .addData(CLASS_INSTANCE, result.getMethod().getInstance()) + .addData( + CLASS_INSTANCE, ((IInstanceInfo) result.getMethod().getInstance()).getInstance()) .addData(GROUPS_DEPENDED_ON, result.getMethod().getGroupsDependedUpon()) .addData(METHODS_DEPENDED_ON, result.getMethod().getMethodsDependedUpon()) .addData(GROUPS_BELONGING_TO, result.getMethod().getGroups()); diff --git a/testng-core/src/test/java/test/tmp/verify/VerifyInterceptor.java b/testng-core/src/test/java/test/tmp/verify/VerifyInterceptor.java index df638e6a1b..c5d8f96a32 100644 --- a/testng-core/src/test/java/test/tmp/verify/VerifyInterceptor.java +++ b/testng-core/src/test/java/test/tmp/verify/VerifyInterceptor.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import org.testng.IInstanceInfo; import org.testng.IMethodInstance; import org.testng.IMethodInterceptor; import org.testng.ITestContext; @@ -56,8 +57,8 @@ public ITestNGMethod getMethod() { } @Override - public Object getInstance() { - return tm.getInstance(); + public IInstanceInfo getInstance() { + return (IInstanceInfo) tm.getInstance(); } }); } diff --git a/testng-runner-api/src/main/java/org/testng/internal/LiteWeightTestNGMethod.java b/testng-runner-api/src/main/java/org/testng/internal/LiteWeightTestNGMethod.java index 06daa522dd..0c5d055bf7 100644 --- a/testng-runner-api/src/main/java/org/testng/internal/LiteWeightTestNGMethod.java +++ b/testng-runner-api/src/main/java/org/testng/internal/LiteWeightTestNGMethod.java @@ -8,6 +8,7 @@ import java.util.concurrent.Callable; import org.testng.IClass; import org.testng.IDataProviderMethod; +import org.testng.IInstanceInfo; import org.testng.IRetryAnalyzer; import org.testng.ITestClass; import org.testng.ITestNGMethod; @@ -20,7 +21,7 @@ public class LiteWeightTestNGMethod implements ITestNGMethod { private final Class realClass; private ITestClass testClass; private final String methodName; - private final Object instance; + private final IInstanceInfo instance; private final long[] instanceHashCodes; private final String[] groups; private final String[] groupsDependedUpon; @@ -71,7 +72,7 @@ public LiteWeightTestNGMethod(ITestNGMethod iTestNGMethod) { realClass = iTestNGMethod.getRealClass(); testClass = iTestNGMethod.getTestClass(); methodName = iTestNGMethod.getMethodName(); - instance = iTestNGMethod.getInstance(); + instance = (IInstanceInfo) iTestNGMethod.getInstance(); instanceHashCodes = iTestNGMethod.getInstanceHashCodes(); groups = iTestNGMethod.getGroups(); groupsDependedUpon = iTestNGMethod.getGroupsDependedUpon(); @@ -182,7 +183,7 @@ public String getMethodName() { } @Override - public Object getInstance() { + public IInstanceInfo getInstance() { return instance; } diff --git a/testng-runner-api/src/main/java/org/testng/internal/TestResult.java b/testng-runner-api/src/main/java/org/testng/internal/TestResult.java index 0817dd11eb..8e4e50f47e 100644 --- a/testng-runner-api/src/main/java/org/testng/internal/TestResult.java +++ b/testng-runner-api/src/main/java/org/testng/internal/TestResult.java @@ -12,7 +12,7 @@ import javax.annotation.Nonnull; import org.testng.IAttributes; import org.testng.IClass; -import org.testng.IFactoryMethod; +import org.testng.IInstanceInfo; import org.testng.ITest; import org.testng.ITestClassInstance; import org.testng.ITestContext; @@ -104,7 +104,7 @@ private void init(ITestNGMethod method, ITestContext ctx, Throwable t, long star } m_context = ctx; - Object instance = method.getInstance(); + Object instance = ((IInstanceInfo) method.getInstance()).getInstance(); // Calculate the name: either the method name, ITest#getTestName or // toString() if it's been overridden. @@ -158,7 +158,7 @@ public String getTestName() { if (this.m_method == null) { return null; } - Object instance = this.m_method.getInstance(); + Object instance = ((IInstanceInfo) this.m_method.getInstance()).getInstance(); if (instance instanceof ITest) { return ((ITest) instance).getTestName(); } @@ -300,15 +300,15 @@ public void setParameters(Object[] parameters) { @Override public Object getInstance() { - return ITestClassInstance.embeddedInstance(this.m_method.getInstance()); + return ((IInstanceInfo) this.m_method.getInstance()).getInstance(); } @Override public Object[] getFactoryParameters() { - return this.m_method - .getFactoryMethod() - .flatMap(IFactoryMethod::getParameters) - .orElse(new Object[0]); + if (!(this.m_method.getInstance() instanceof ITestClassInstance)) { + return new Object[0]; + } + return ((ITestClassInstance) this.m_method.getInstance()).getFactoryMethod().getParameters(); } @Override