org.testng.internal.ConfigurationGroupMethods Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of testng Show documentation
Show all versions of testng Show documentation
Testing framework for Java
package org.testng.internal;
import org.testng.ITestNGMethod;
import org.testng.collections.Lists;
import org.testng.collections.Maps;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* This class wraps access to beforeGroups and afterGroups methods, since they are passed around the
* various invokers and potentially modified in different threads.
*
* @since 5.3 (Mar 2, 2006)
*/
public class ConfigurationGroupMethods {
/** The list of beforeGroups methods keyed by the name of the group */
private final Map> m_beforeGroupsMethods;
private final Set beforeGroupsThatHaveAlreadyRun =
Collections.newSetFromMap(new ConcurrentHashMap<>());
private final Set afterGroupsThatHaveAlreadyRun =
Collections.newSetFromMap(new ConcurrentHashMap<>());
/** The list of afterGroups methods keyed by the name of the group */
private final Map> m_afterGroupsMethods;
/** The list of all test methods */
private final ITestNGMethod[] m_allMethods;
/** A map that returns the last method belonging to the given group */
private volatile Map> m_afterGroupsMap = null;
public ConfigurationGroupMethods(
ITestNGMethod[] allMethods,
Map> beforeGroupsMethods,
Map> afterGroupsMethods) {
m_allMethods = allMethods;
m_beforeGroupsMethods = new ConcurrentHashMap<>(beforeGroupsMethods);
m_afterGroupsMethods = new ConcurrentHashMap<>(afterGroupsMethods);
}
public ITestNGMethod[] getAllTestMethods() {
return this.m_allMethods;
}
public Map> getBeforeGroupsMethods() {
return m_beforeGroupsMethods;
}
public Map> getAfterGroupsMethods() {
return m_afterGroupsMethods;
}
/**
* @return true if the passed method is the last to run for the group. This method is used to
* figure out when is the right time to invoke afterGroups methods.
*/
public boolean isLastMethodForGroup(String group, ITestNGMethod method) {
// If we have more invocation to do, this is not the last one yet
if (method.hasMoreInvocation()) {
return false;
}
// This Mutex ensures that this edit check runs sequentially for one ITestNGMethod
// method at a time because this object is being shared between all the ITestNGMethod objects.
synchronized (this) {
if (m_afterGroupsMap == null) {
m_afterGroupsMap = initializeAfterGroupsMap();
}
List methodsInGroup = m_afterGroupsMap.get(group);
if (null == methodsInGroup || methodsInGroup.isEmpty()) {
return false;
}
methodsInGroup.remove(method);
// Note: == is not good enough here as we may work with ITestNGMethod clones
return methodsInGroup.isEmpty();
}
}
private Map> initializeAfterGroupsMap() {
Map> result = Maps.newConcurrentMap();
for (ITestNGMethod m : m_allMethods) {
String[] groups = m.getGroups();
for (String g : groups) {
List methodsInGroup = result.computeIfAbsent(g, key -> Lists.newArrayList());
methodsInGroup.add(m);
}
}
synchronized (afterGroupsThatHaveAlreadyRun) {
afterGroupsThatHaveAlreadyRun.clear();
}
return result;
}
public List getBeforeGroupMethodsForGroup(String group) {
synchronized (beforeGroupsThatHaveAlreadyRun) {
return retrieve(beforeGroupsThatHaveAlreadyRun, m_beforeGroupsMethods, group);
}
}
public List getAfterGroupMethodsForGroup(String group) {
synchronized (afterGroupsThatHaveAlreadyRun) {
return retrieve(afterGroupsThatHaveAlreadyRun, m_afterGroupsMethods, group);
}
}
public void removeBeforeGroups(String[] groups) {
for (String group : groups) {
m_beforeGroupsMethods.remove(group);
}
}
public void removeAfterGroups(Collection groups) {
for (String group : groups) {
m_afterGroupsMethods.remove(group);
}
}
private static List retrieve(
Set tracker, Map> map, String group) {
if (tracker.contains(group)) {
return Collections.emptyList();
}
tracker.add(group);
return map.get(group);
}
}