/*
* JBoss, Home of Professional Open Source
* Copyright 2009 Red Hat Inc. and/or its affiliates and other
* contributors as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a full listing of
* individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.infinispan.test.fwk;
import org.infinispan.config.Configuration;
import org.infinispan.config.FluentConfiguration;
import org.infinispan.config.GlobalConfiguration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.configuration.parsing.ConfigurationBuilderHolder;
import org.infinispan.configuration.parsing.Parser;
import org.infinispan.jmx.PerThreadMBeanServerLookup;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.marshall.Marshaller;
import org.infinispan.remoting.transport.jgroups.JGroupsTransport;
import org.infinispan.transaction.TransactionMode;
import org.infinispan.transaction.lookup.TransactionManagerLookup;
import org.infinispan.util.FileLookupFactory;
import org.infinispan.util.LegacyKeySupportSystemProperties;
import org.infinispan.util.Util;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import static org.infinispan.test.fwk.JGroupsConfigBuilder.getJGroupsConfig;
/**
* CacheManagers in unit tests should be created with this factory, in order to avoid resource clashes. See
* http://community.jboss.org/wiki/ParallelTestSuite for more details.
*
* @author Mircea.Markus@jboss.com
* @author Galder ZamarreƱo
*/
public class TestCacheManagerFactory {
private static AtomicInteger jmxDomainPostfix = new AtomicInteger();
public static final String MARSHALLER = LegacyKeySupportSystemProperties.getProperty("infinispan.test.marshaller.class", "infinispan.marshaller.class");
private static final Log log = LogFactory.getLog(TestCacheManagerFactory.class);
private static volatile boolean shuttingDown;
private static CountDownLatch shutDownLatch = new CountDownLatch(1);
private static ThreadLocal<PerThreadCacheManagers> perThreadCacheManagers = new ThreadLocal<PerThreadCacheManagers>() {
@Override
protected PerThreadCacheManagers initialValue() {
return new PerThreadCacheManagers();
}
};
private static DefaultCacheManager newDefaultCacheManager(boolean start, GlobalConfiguration gc, Configuration c, boolean keepJmxDomain) {
if (!keepJmxDomain) {
gc.setJmxDomain("infinispan" + jmxDomainPostfix.incrementAndGet());
}
return newDefaultCacheManager(start, gc, c);
}
private static DefaultCacheManager newDefaultCacheManager(boolean start, GlobalConfigurationBuilder gc, ConfigurationBuilder c, boolean keepJmxDomain) {
if (!keepJmxDomain) {
gc.globalJmxStatistics().jmxDomain("infinispan" + jmxDomainPostfix.incrementAndGet());
}
return newDefaultCacheManager(start, gc, c);
}
private static DefaultCacheManager newDefaultCacheManager(boolean start, ConfigurationBuilderHolder holder, boolean keepJmxDomain) {
if (!keepJmxDomain) {
holder.getGlobalConfigurationBuilder().globalJmxStatistics().jmxDomain(
"infinispan" + jmxDomainPostfix.incrementAndGet());
}
return newDefaultCacheManager(start, holder);
}
public static EmbeddedCacheManager fromXml(String xmlFile) throws IOException {
return fromXml(xmlFile, false);
}
public static EmbeddedCacheManager fromXml(String xmlFile, boolean keepJmxDomainName) throws IOException {
InputStream is = FileLookupFactory.newInstance().lookupFileStrict(
xmlFile, Thread.currentThread().getContextClassLoader());
return fromStream(is, keepJmxDomainName);
}
public static EmbeddedCacheManager fromStream(InputStream is) throws IOException {
return fromStream(is, false);
}
public static EmbeddedCacheManager fromStream(InputStream is, boolean keepJmxDomainName) throws IOException {
ConfigurationBuilderHolder holder = new Parser(
Thread.currentThread().getContextClassLoader()).parse(is);
return createClusteredCacheManager(holder, keepJmxDomainName);
}
/**
* Creates an cache manager that does not support clustering.
*
* @param transactional if true, the cache manager will support transactions by default.
*/
public static EmbeddedCacheManager createLocalCacheManager(boolean transactional) {
return createLocalCacheManager(transactional, -1);
}
public static EmbeddedCacheManager createLocalCacheManager(boolean transactional, long lockAcquisitionTimeout) {
GlobalConfiguration globalConfiguration = GlobalConfiguration.getNonClusteredDefault();
amendMarshaller(globalConfiguration);
minimizeThreads(globalConfiguration);
Configuration c = new Configuration();
markAsTransactional(transactional, c);
if (lockAcquisitionTimeout > -1) c.setLockAcquisitionTimeout(lockAcquisitionTimeout);
updateTransactionSupport(c);
return newDefaultCacheManager(true, globalConfiguration, c, false);
}
private static void markAsTransactional(boolean transactional, Configuration c) {
c.fluent().transaction().transactionMode(transactional ? TransactionMode.TRANSACTIONAL : TransactionMode.NON_TRANSACTIONAL);
}
private static void markAsTransactional(boolean transactional, ConfigurationBuilder builder) {
builder.transaction().transactionMode(transactional ? TransactionMode.TRANSACTIONAL : TransactionMode.NON_TRANSACTIONAL);
}
private static void updateTransactionSupport(Configuration c) {
if (c.isTransactionalCache()) amendJTA(c);
}
private static void updateTransactionSupport(boolean transactional, ConfigurationBuilder builder) {
if (transactional) amendJTA(builder);
}
private static void amendJTA(Configuration c) {
if (c.isTransactionalCache() && c.getTransactionManagerLookupClass() == null && c.getTransactionManagerLookup() == null) {
c.setTransactionManagerLookupClass(TransactionSetup.getManagerLookup());
}
}
private static void amendJTA(ConfigurationBuilder builder) {
org.infinispan.configuration.cache.Configuration c = builder.build();
if (c.transaction().transactionMode().equals(TransactionMode.TRANSACTIONAL) && c.transaction().transactionManagerLookup() == null) {
builder.transaction().transactionManagerLookup((TransactionManagerLookup) Util.getInstance(TransactionSetup.getManagerLookup(), TestCacheManagerFactory.class.getClassLoader()));
}
}
/**
* Creates an cache manager that does support clustering.
*/
public static EmbeddedCacheManager createClusteredCacheManager() {
return createClusteredCacheManager(new TransportFlags());
}
public static EmbeddedCacheManager createClusteredCacheManager(TransportFlags flags) {
return createClusteredCacheManager(new Configuration(), flags);
}
public static EmbeddedCacheManager createClusteredCacheManager(Configuration defaultCacheConfig) {
return createClusteredCacheManager(defaultCacheConfig, new TransportFlags());
}
public static EmbeddedCacheManager createClusteredCacheManager(Configuration defaultCacheConfig, TransportFlags flags) {
GlobalConfiguration globalConfiguration = GlobalConfiguration.getClusteredDefault();
amendMarshaller(globalConfiguration);
minimizeThreads(globalConfiguration);
amendTransport(globalConfiguration, flags);
amendJTA(defaultCacheConfig);
return newDefaultCacheManager(true, globalConfiguration, defaultCacheConfig, false);
}
public static EmbeddedCacheManager createClusteredCacheManager(ConfigurationBuilder defaultCacheConfig, TransportFlags flags) {
return createClusteredCacheManager(GlobalConfigurationBuilder.defaultClusteredBuilder(), defaultCacheConfig, flags);
}
public static EmbeddedCacheManager createClusteredCacheManager(GlobalConfigurationBuilder gcb, ConfigurationBuilder defaultCacheConfig) {
return createClusteredCacheManager(gcb, defaultCacheConfig, new TransportFlags());
}
public static EmbeddedCacheManager createClusteredCacheManager(ConfigurationBuilder defaultCacheConfig) {
return createClusteredCacheManager(GlobalConfigurationBuilder.defaultClusteredBuilder(), defaultCacheConfig);
}
public static EmbeddedCacheManager createClusteredCacheManager(ConfigurationBuilderHolder holder) {
return createClusteredCacheManager(holder, false);
}
public static EmbeddedCacheManager createClusteredCacheManager(ConfigurationBuilderHolder holder, boolean keepJmxDomainName) {
TransportFlags flags = new TransportFlags();
amendGlobalConfiguration(holder.getGlobalConfigurationBuilder(), flags);
amendJTA(holder.getDefaultConfigurationBuilder());
for (ConfigurationBuilder builder : holder.getNamedConfigurationBuilders().values())
amendJTA(builder);
return newDefaultCacheManager(true, holder, keepJmxDomainName);
}
public static EmbeddedCacheManager createClusteredCacheManager(GlobalConfigurationBuilder gcb, ConfigurationBuilder defaultCacheConfig, TransportFlags flags) {
amendGlobalConfiguration(gcb, flags);
amendJTA(defaultCacheConfig);
return newDefaultCacheManager(true, gcb, defaultCacheConfig, false);
}
public static void amendGlobalConfiguration(GlobalConfigurationBuilder gcb, TransportFlags flags) {
amendMarshaller(gcb);
minimizeThreads(gcb);
amendTransport(gcb, flags);
}
public static EmbeddedCacheManager createCacheManager(ConfigurationBuilder builder) {
return createCacheManager(new GlobalConfigurationBuilder().nonClusteredDefault(), builder);
}
public static EmbeddedCacheManager createCacheManager(GlobalConfigurationBuilder globalBuilder, ConfigurationBuilder builder) {
return newDefaultCacheManager(true, globalBuilder, builder, false);
}
/**
* Creates a cache manager and amends the supplied configuration in order to avoid conflicts (e.g. jmx, jgroups)
* during running tests in parallel.
*/
public static EmbeddedCacheManager createCacheManager(GlobalConfiguration configuration) {
return internalCreateJmxDomain(true, configuration, false);
}
public static EmbeddedCacheManager createCacheManager(boolean start, GlobalConfiguration configuration) {
return internalCreateJmxDomain(start, configuration, false);
}
/**
* Creates a cache manager that won't try to modify the configured jmx domain name: {@link
* org.infinispan.config.GlobalConfiguration#getJmxDomain()}. This method must be used with care, and one should
* make sure that no domain name collision happens when the parallel suite executes. An approach to ensure this, is
* to set the domain name to the name of the test class that instantiates the CacheManager.
*/
public static EmbeddedCacheManager createCacheManagerEnforceJmxDomain(GlobalConfiguration configuration) {
return internalCreateJmxDomain(true, configuration, true);
}
private static EmbeddedCacheManager internalCreateJmxDomain(boolean start, GlobalConfiguration configuration, boolean enforceJmxDomain) {
amendMarshaller(configuration);
minimizeThreads(configuration);
amendTransport(configuration);
return newDefaultCacheManager(start, configuration, new Configuration(), enforceJmxDomain);
}
public static EmbeddedCacheManager createCacheManager(Configuration.CacheMode mode, boolean indexing) {
GlobalConfiguration gc = mode.isClustered() ? GlobalConfiguration.getClusteredDefault() : GlobalConfiguration.getNonClusteredDefault();
Configuration c = new Configuration();
FluentConfiguration fluentConfiguration = c.fluent();
if (indexing) {
//The property is not really needed as it defaults to the same value,
//but since it's recommended we set it explicitly to avoid logging a noisy warning.
fluentConfiguration.indexing().addProperty("hibernate.search.lucene_version", "LUCENE_CURRENT");
}
fluentConfiguration.mode(mode);
return createCacheManager(gc, fluentConfiguration.build());
}
public static EmbeddedCacheManager createCacheManager(Configuration defaultCacheConfig) {
GlobalConfiguration globalConfiguration;
if (defaultCacheConfig.getCacheMode().isClustered()) {
globalConfiguration = GlobalConfiguration.getClusteredDefault();
amendTransport(globalConfiguration);
}
else {
globalConfiguration = GlobalConfiguration.getNonClusteredDefault();
}
amendMarshaller(globalConfiguration);
minimizeThreads(globalConfiguration);
updateTransactionSupport(defaultCacheConfig);
// we stop caches during transactions all the time
// so wait at most 1 second for ongoing transactions when stopping
defaultCacheConfig.fluent().cacheStopTimeout(1000);
return newDefaultCacheManager(true, globalConfiguration, defaultCacheConfig, false);
}
public static EmbeddedCacheManager createCacheManager(GlobalConfiguration configuration, Configuration defaultCfg) {
minimizeThreads(configuration);
amendMarshaller(configuration);
amendTransport(configuration);
updateTransactionSupport(defaultCfg);
return newDefaultCacheManager(true, configuration, defaultCfg, false);
}
public static EmbeddedCacheManager createCacheManager(GlobalConfiguration configuration, Configuration defaultCfg, boolean keepJmxDomainName) {
return createCacheManager(configuration, defaultCfg, keepJmxDomainName, false);
}
public static EmbeddedCacheManager createCacheManager(GlobalConfiguration configuration, Configuration defaultCfg, boolean keepJmxDomainName, boolean dontFixTransport) {
minimizeThreads(configuration);
amendMarshaller(configuration);
if (!dontFixTransport) amendTransport(configuration);
updateTransactionSupport(defaultCfg);
return newDefaultCacheManager(true, configuration, defaultCfg, keepJmxDomainName);
}
/**
* @see #createCacheManagerEnforceJmxDomain(String)
*/
public static EmbeddedCacheManager createCacheManagerEnforceJmxDomain(String jmxDomain) {
return createCacheManagerEnforceJmxDomain(jmxDomain, true, true);
}
/**
* @see #createCacheManagerEnforceJmxDomain(String)
*/
public static EmbeddedCacheManager createCacheManagerEnforceJmxDomain(String jmxDomain, boolean exposeGlobalJmx, boolean exposeCacheJmx) {
return createCacheManagerEnforceJmxDomain(jmxDomain, null, exposeGlobalJmx, exposeCacheJmx);
}
/**
* @see #createCacheManagerEnforceJmxDomain(String)
*/
public static EmbeddedCacheManager createCacheManagerEnforceJmxDomain(String jmxDomain, String cacheManagerName, boolean exposeGlobalJmx, boolean exposeCacheJmx) {
GlobalConfiguration globalConfiguration = GlobalConfiguration.getNonClusteredDefault();
globalConfiguration.setJmxDomain(jmxDomain);
if (cacheManagerName != null)
globalConfiguration.setCacheManagerName(cacheManagerName);
globalConfiguration.setMBeanServerLookup(PerThreadMBeanServerLookup.class.getName());
globalConfiguration.setExposeGlobalJmxStatistics(exposeGlobalJmx);
Configuration configuration = new Configuration();
configuration.setExposeJmxStatistics(exposeCacheJmx);
return createCacheManager(globalConfiguration, configuration, true);
}
public static Configuration getDefaultConfiguration(boolean transactional) {
Configuration c = new Configuration();
markAsTransactional(transactional, c);
updateTransactionSupport(c);
return c;
}
public static ConfigurationBuilder getDefaultCacheConfiguration(boolean transactional) {
return getDefaultCacheConfiguration(transactional, false);
}
public static ConfigurationBuilder getDefaultCacheConfiguration(boolean transactional, boolean useCustomTxLookup) {
ConfigurationBuilder builder = new ConfigurationBuilder();
markAsTransactional(transactional, builder);
//don't changed the tx lookup.
if (useCustomTxLookup) updateTransactionSupport(transactional, builder);
return builder;
}
public static Configuration getDefaultConfiguration(boolean transactional, Configuration.CacheMode cacheMode) {
Configuration c = new Configuration();
markAsTransactional(transactional, c);
updateTransactionSupport(c);
c.setCacheMode(cacheMode);
if (cacheMode.isClustered()) {
c.setSyncRollbackPhase(true);
c.setSyncCommitPhase(true);
}
return c;
}
public static void amendTransport(GlobalConfiguration cfg) {
amendTransport(cfg, new TransportFlags());
}
private static void amendTransport(GlobalConfiguration configuration, TransportFlags flags) {
if (configuration.getTransportClass() != null) { //this is local
Properties newTransportProps = new Properties();
Properties previousSettings = configuration.getTransportProperties();
if (previousSettings != null) {
newTransportProps.putAll(previousSettings);
}
String fullTestName = perThreadCacheManagers.get().fullTestName;
String nextCacheName = perThreadCacheManagers.get().getNextCacheName();
checkTestName(fullTestName);
newTransportProps.put(JGroupsTransport.CONFIGURATION_STRING,
getJGroupsConfig(fullTestName, flags));
configuration.setTransportProperties(newTransportProps);
configuration.setTransportNodeName(nextCacheName);
}
}
private static void amendTransport(GlobalConfigurationBuilder builder, TransportFlags flags) {
org.infinispan.configuration.global.GlobalConfiguration gc = builder.build();
if (gc.transport().transport() != null) { //this is local
String fullTestName = perThreadCacheManagers.get().fullTestName;
String nextCacheName = perThreadCacheManagers.get().getNextCacheName();
checkTestName(fullTestName);
// Remove any configuration file that might have been set.
builder.transport().removeProperty(JGroupsTransport.CONFIGURATION_FILE);
builder
.transport()
.addProperty(JGroupsTransport.CONFIGURATION_STRING, getJGroupsConfig(fullTestName, flags))
.nodeName(nextCacheName);
}
}
private static void checkTestName(String fullTestName) {
if (fullTestName == null) {
// Either we're running from within the IDE or it's a
// @Test(timeOut=nnn) test. We rely here on some specific TestNG
// thread naming convention which can break, but TestNG offers no
// other alternative. It does not offer any callbacks within the
// thread that runs the test that can timeout.
String threadName = Thread.currentThread().getName();
String pattern = "TestNGInvoker-";
if (threadName.startsWith(pattern)) {
// This is a timeout test, so force the user to call our marking method
throw new RuntimeException("Test name is not set! Please call TestCacheManagerFactory.backgroundTestStarted(this) in your test method!");
} // else, test is being run from IDE
}
}
public static void minimizeThreads(GlobalConfiguration gc) {
Properties p = new Properties();
p.setProperty("maxThreads", "4");
gc.setAsyncTransportExecutorProperties(p);
}
public static void minimizeThreads(GlobalConfigurationBuilder builder) {
builder.asyncTransportExecutor().addProperty("maxThreads", "4");
}
public static void amendMarshaller(GlobalConfiguration configuration) {
if (MARSHALLER != null) {
try {
Util.loadClassStrict(MARSHALLER, Thread.currentThread().getContextClassLoader());
configuration.setMarshallerClass(MARSHALLER);
} catch (ClassNotFoundException e) {
// No-op, stick to GlobalConfiguration default.
}
}
}
@SuppressWarnings("unchecked")
public static void amendMarshaller(GlobalConfigurationBuilder builder) {
if (MARSHALLER != null) {
try {
Marshaller marshaller = Util.getInstanceStrict(MARSHALLER, Thread.currentThread().getContextClassLoader());
builder.serialization().marshaller(marshaller);
} catch (ClassNotFoundException e) {
// No-op, stick to GlobalConfiguration default.
} catch (InstantiationException e) {
// No-op, stick to GlobalConfiguration default.
} catch (IllegalAccessException e) {
// No-op, stick to GlobalConfiguration default.
}
}
}
private static DefaultCacheManager newDefaultCacheManager(boolean start, GlobalConfiguration gc, Configuration c) {
DefaultCacheManager defaultCacheManager = new DefaultCacheManager(gc, c, start);
return addThreadCacheManager(defaultCacheManager);
}
private static DefaultCacheManager newDefaultCacheManager(boolean start, GlobalConfigurationBuilder gc, ConfigurationBuilder c) {
DefaultCacheManager defaultCacheManager = new DefaultCacheManager(gc.build(), c.build(), start);
return addThreadCacheManager(defaultCacheManager);
}
private static DefaultCacheManager newDefaultCacheManager(boolean start, ConfigurationBuilderHolder holder) {
DefaultCacheManager defaultCacheManager = new DefaultCacheManager(holder, start);
return addThreadCacheManager(defaultCacheManager);
}
private static DefaultCacheManager addThreadCacheManager(DefaultCacheManager cm) {
if (shuttingDown) {
try {
shutDownLatch.await();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
PerThreadCacheManagers threadCacheManagers = perThreadCacheManagers.get();
String methodName = extractMethodName();
log.trace("Adding DCM (" + cm.getAddress() + ") for method: '" + methodName + "'");
threadCacheManagers.add(methodName, cm);
return cm;
}
private static String extractMethodName() {
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
if (stack.length == 0) return null;
for (int i = stack.length - 1; i > 0; i--) {
StackTraceElement e = stack[i];
String className = e.getClassName();
if ((className.indexOf("org.infinispan") != -1) && className.indexOf("org.infinispan.test") < 0)
return e.toString();
}
return null;
}
public static void backgroundTestStarted(Object testInstance) {
String fullName = testInstance.getClass().getName();
String testName = testInstance.getClass().getSimpleName();
TestCacheManagerFactory.testStarted(testName, fullName);
}
static void testStarted(String testName, String fullName) {
perThreadCacheManagers.get().setTestName(testName, fullName);
}
static void testFinished(String testName) {
perThreadCacheManagers.get().checkManagersClosed(testName);
perThreadCacheManagers.get().unsetTestName();
}
public static DefaultCacheManager createCacheManager(org.infinispan.configuration.cache.Configuration config) {
GlobalConfigurationBuilder globalConfigBuilder = GlobalConfigurationBuilder.defaultClusteredBuilder();
TestCacheManagerFactory.amendGlobalConfiguration(globalConfigBuilder, new TransportFlags());
return new DefaultCacheManager(globalConfigBuilder.build(), config);
}
private static class PerThreadCacheManagers {
String testName = null;
private String oldThreadName;
HashMap<EmbeddedCacheManager, String> cacheManagers = new HashMap<EmbeddedCacheManager, String>();
String fullTestName;
public void checkManagersClosed(String testName) {
for (Map.Entry<EmbeddedCacheManager, String> cmEntry : cacheManagers.entrySet()) {
if (cmEntry.getKey().getStatus().allowInvocations()) {
String thName = Thread.currentThread().getName();
String errorMessage = '\n' +
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" +
"!!!!!! (" + thName + ") Exiting because " + testName + " has NOT shut down all the cache managers it has started !!!!!!!\n" +
"!!!!!! (" + thName + ") The still-running cacheManager was created here: " + cmEntry.getValue() + " !!!!!!!\n" +
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
log.error(errorMessage);
shuttingDown = true;//just reduce noise..
try {
Thread.sleep(60000); //wait for the thread dump to be logged in case of OOM
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println(errorMessage);
System.exit(9);
}
}
cacheManagers.clear();
}
public String getNextCacheName() {
int index = cacheManagers.size();
char name = (char) ((int) 'A' + index);
return (testName != null ? testName + "-" : "") + "Node" + name;
}
public void add(String methodName, DefaultCacheManager cm) {
cacheManagers.put(cm, methodName);
}
public void setTestName(String testName, String fullTestName) {
this.testName = testName;
this.fullTestName = fullTestName;
this.oldThreadName = Thread.currentThread().getName();
Thread.currentThread().setName("testng-" + testName);
}
public void unsetTestName() {
this.testName = null;
Thread.currentThread().setName(oldThreadName);
this.oldThreadName = null;
}
}
}