Skip to content

Commit

Permalink
performance enhancements when dealing with large numbers of methods. …
Browse files Browse the repository at this point in the history
  • Loading branch information
benlamonica committed Aug 5, 2015
2 parents 6768e00 + 94b2285 commit db7b66a
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 61 deletions.
32 changes: 21 additions & 11 deletions src/main/java/org/testng/TestClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,55 +122,65 @@ public void addInstance(Object instance) {
private void initMethods() {
ITestNGMethod[] methods = m_testMethodFinder.getTestMethods(m_testClass, m_xmlTest);
m_testMethods = createTestMethods(methods);

// moving these out of the loops reduces creation time of the methods from 196 seconds to 2 seconds under extreme circumstances
ITestNGMethod[] beforeSuiteMethods = m_testMethodFinder.getBeforeSuiteMethods(m_testClass);
ITestNGMethod[] afterSuiteMethods = m_testMethodFinder.getAfterSuiteMethods(m_testClass);
ITestNGMethod[] beforeTestConfMethods = m_testMethodFinder.getBeforeTestConfigurationMethods(m_testClass);
ITestNGMethod[] afterTestConfMethods = m_testMethodFinder.getAfterTestConfigurationMethods(m_testClass);
ITestNGMethod[] beforeClassMethods = m_testMethodFinder.getBeforeClassMethods(m_testClass);
ITestNGMethod[] afterClassMethods = m_testMethodFinder.getAfterClassMethods(m_testClass);
ITestNGMethod[] beforeGroupsMethods = m_testMethodFinder.getBeforeGroupsConfigurationMethods(m_testClass);
ITestNGMethod[] afterGroupsMethods = m_testMethodFinder.getAfterGroupsConfigurationMethods(m_testClass);
ITestNGMethod[] beforeTestMethods = m_testMethodFinder.getBeforeTestMethods(m_testClass);
ITestNGMethod[] afterTestMethods = m_testMethodFinder.getAfterTestMethods(m_testClass);
for (Object instance : m_iClass.getInstances(false)) {
m_beforeSuiteMethods = ConfigurationMethod
.createSuiteConfigurationMethods(m_testMethodFinder.getBeforeSuiteMethods(m_testClass),
.createSuiteConfigurationMethods(beforeSuiteMethods,
m_annotationFinder,
true,
instance);
m_afterSuiteMethods = ConfigurationMethod
.createSuiteConfigurationMethods(m_testMethodFinder.getAfterSuiteMethods(m_testClass),
.createSuiteConfigurationMethods(afterSuiteMethods,
m_annotationFinder,
false,
instance);
m_beforeTestConfMethods = ConfigurationMethod
.createTestConfigurationMethods(m_testMethodFinder.getBeforeTestConfigurationMethods(m_testClass),
.createTestConfigurationMethods(beforeTestConfMethods,
m_annotationFinder,
true,
instance);
m_afterTestConfMethods = ConfigurationMethod
.createTestConfigurationMethods(m_testMethodFinder.getAfterTestConfigurationMethods(m_testClass),
.createTestConfigurationMethods(afterTestConfMethods,
m_annotationFinder,
false,
instance);
m_beforeClassMethods = ConfigurationMethod
.createClassConfigurationMethods(m_testMethodFinder.getBeforeClassMethods(m_testClass),
.createClassConfigurationMethods(beforeClassMethods,
m_annotationFinder,
true,
instance);
m_afterClassMethods = ConfigurationMethod
.createClassConfigurationMethods(m_testMethodFinder.getAfterClassMethods(m_testClass),
.createClassConfigurationMethods(afterClassMethods,
m_annotationFinder,
false,
instance);
m_beforeGroupsMethods = ConfigurationMethod
.createBeforeConfigurationMethods(m_testMethodFinder.getBeforeGroupsConfigurationMethods(m_testClass),
.createBeforeConfigurationMethods(beforeGroupsMethods,
m_annotationFinder,
true,
instance);
m_afterGroupsMethods = ConfigurationMethod
.createAfterConfigurationMethods(m_testMethodFinder.getAfterGroupsConfigurationMethods(m_testClass),
.createAfterConfigurationMethods(afterGroupsMethods,
m_annotationFinder,
false,
instance);
m_beforeTestMethods = ConfigurationMethod
.createTestMethodConfigurationMethods(m_testMethodFinder.getBeforeTestMethods(m_testClass),
.createTestMethodConfigurationMethods(beforeTestMethods,
m_annotationFinder,
true,
instance);
m_afterTestMethods = ConfigurationMethod
.createTestMethodConfigurationMethods(m_testMethodFinder.getAfterTestMethods(m_testClass),
.createTestMethodConfigurationMethods(afterTestMethods,
m_annotationFinder,
false,
instance);
Expand Down
66 changes: 35 additions & 31 deletions src/main/java/org/testng/internal/BaseTestMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -396,40 +396,44 @@ public boolean canRunFromClass(IClass testClass) {
return m_methodClass.isAssignableFrom(testClass.getRealClass());
}

/**
* {@inheritDoc} Compares two BaseTestMethod using the test class then the associated
* Java Method.
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}

BaseTestMethod other = (BaseTestMethod) obj;

boolean isEqual = m_testClass == null ? other.m_testClass == null
: other.m_testClass != null &&
m_testClass.getRealClass().equals(other.m_testClass.getRealClass())
&& m_instance == other.getInstance();

return isEqual && getConstructorOrMethod().equals(other.getConstructorOrMethod());
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseTestMethod other = (BaseTestMethod) obj;
if (m_instance == null) {
if (other.m_instance != null)
return false;
} else if (!m_instance.equals(other.m_instance))
return false;
if (m_method == null) {
if (other.m_method != null)
return false;
} else if (!m_method.equals(other.m_method))
return false;
if (m_testClass == null) {
if (other.m_testClass != null)
return false;
} else if (!m_testClass.equals(other.m_testClass))
return false;
return true;
}

/**
* {@inheritDoc} This implementation returns the associated Java Method's hash code.
* @return the associated Java Method's hash code.
*/
@Override
public int hashCode() {
return m_method.hashCode();
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((m_instance == null) ? 0 : m_instance.hashCode());
result = prime * result + ((m_method == null) ? 0 : m_method.hashCode());
result = prime * result
+ ((m_testClass == null) ? 0 : m_testClass.hashCode());
return result;
}

protected void initGroups(Class<? extends ITestOrConfiguration> annotationClass) {
//
Expand Down
22 changes: 12 additions & 10 deletions src/main/java/org/testng/internal/Graph.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public void topologicalSort() {
for (Node<T> n : getNodes()) {
if (! isIndependent(n.getObject())) {
ppp("ADDING FOR SORT: " + n.getObject());
nodes2.add(n.clone());
nodes2.add(n);
}
else {
ppp("SKIPPING INDEPENDENT NODE " + n);
Expand Down Expand Up @@ -287,15 +287,17 @@ public Map<T, T> getPredecessors() {
public boolean removePredecessor(T o) {
boolean result = false;

T pred = m_predecessors.get(o);
if (null != pred) {
result = null != m_predecessors.remove(o);
if (result) {
ppp(" REMOVED PRED " + o + " FROM NODE " + m_object);
}
else {
ppp(" FAILED TO REMOVE PRED " + o + " FROM NODE " + m_object);
}
if (!m_predecessors.isEmpty()) {
T pred = m_predecessors.get(o);
if (null != pred) {
result = null != m_predecessors.remove(o);
if (result) {
ppp(" REMOVED PRED " + o + " FROM NODE " + m_object);
}
else {
ppp(" FAILED TO REMOVE PRED " + o + " FROM NODE " + m_object);
}
}
}

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import org.testng.annotations.TestInstance;
import org.testng.internal.collections.Pair;

import com.google.common.collect.Maps;

/**
* This class implements IAnnotationFinder with JDK5 annotations
*
Expand Down Expand Up @@ -97,16 +99,32 @@ private <A extends Annotation> A findAnnotationInSuperClasses(Class<?> cls, Clas
return null;
}

@Override
private Map<Pair,IAnnotation> annotationCache = Maps.newConcurrentMap();
private final static IAnnotation NULL_CACHE_ENTRY = new IAnnotation() {};
@Override
public <A extends IAnnotation> A findAnnotation(Method m, Class<A> annotationClass) {
final Class<? extends Annotation> a = m_annotationMap.get(annotationClass);
if (a == null) {
throw new IllegalArgumentException("Java @Annotation class for '"
+ annotationClass + "' not found.");
}
Annotation annotation = m.getAnnotation(a);
return findAnnotation(m.getDeclaringClass(), annotation, annotationClass, null, null, m,
new Pair<>(annotation, m));
Pair<Method,Class<A>> cacheKey = new Pair<>(m,annotationClass);
IAnnotation cachedValue = annotationCache.get(cacheKey);
if (cachedValue == null) {
final Class<? extends Annotation> a = m_annotationMap.get(annotationClass);
if (a == null) {
throw new IllegalArgumentException("Java @Annotation class for '"
+ annotationClass + "' not found.");
}
Annotation annotation = m.getAnnotation(a);
cachedValue = findAnnotation(m.getDeclaringClass(), annotation, annotationClass, null, null, m,
new Pair<>(annotation, m));
if (cachedValue == null) {
cachedValue = NULL_CACHE_ENTRY;
}
annotationCache.put(cacheKey, cachedValue);
}

if (cachedValue == NULL_CACHE_ENTRY) {
return null;
} else {
return (A) cachedValue;
}
}

@Override
Expand Down

0 comments on commit db7b66a

Please sign in to comment.