/**
* Copyright (C) 2008 Mathieu Carbou <mathieu.carbou@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mycila.testing.core;
import com.mycila.log.Logger;
import com.mycila.log.Loggers;
import com.mycila.plugin.api.PluginBinding;
import com.mycila.plugin.spi.PluginManager;
import com.mycila.testing.core.api.Attributes;
import static com.mycila.testing.core.api.Ensure.*;
import com.mycila.testing.core.api.Step;
import com.mycila.testing.core.api.TestContext;
import com.mycila.testing.core.api.TestNotifier;
import com.mycila.testing.core.api.TestPluginException;
import com.mycila.testing.core.introspect.Introspector;
import com.mycila.testing.core.plugin.TestPlugin;
import java.lang.reflect.Method;
/**
* @author Mathieu Carbou (mathieu.carbou@gmail.com)
*/
final class TestContextImpl implements TestContext, TestNotifier {
private static final Method prepareMethod;static {
try {
prepareMethod = TestNotifier.class.getDeclaredMethod("prepare");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private static final Method fireAfterClassMethod;static {
try {
fireAfterClassMethod = TestNotifier.class.getDeclaredMethod("fireAfterClass");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private static final Method shutdownMethod;static {
try {
shutdownMethod = TestNotifier.class.getDeclaredMethod("shutdown");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private static final Logger LOGGER = Loggers.get(TestContextImpl.class);
private final Introspector introspector;
private final PluginManager<TestPlugin> pluginManager;
private final Attributes attributes = new AttributesImpl();
TestContextImpl(PluginManager<TestPlugin> pluginManager, Object testInstance) {
notNull("Plugin manager", pluginManager);
notNull("Test instance", testInstance);
this.introspector = new Introspector(testInstance);
this.pluginManager = pluginManager;
LOGGER.debug("Creating new Test Context for test %s#%s", this.introspector.testClass().getName(), this.introspector.instance().hashCode());
Mycila.registerContext(this);
}
public PluginManager<TestPlugin> pluginManager() {
return pluginManager;
}
public Introspector introspector() {
return introspector;
}
public Attributes attributes() {
return attributes;
}
public void prepare() throws TestPluginException {
try {
ExecutionImpl execution = new ExecutionImpl(this, prepareMethod);
Mycila.registerCurrentExecution(execution.changeStep(Step.PREPARE));
LOGGER.debug("Calling 'prepareTestInstance' on plugins for test %s#%s...", introspector.testClass().getName(), introspector.instance().hashCode());
for (PluginBinding<TestPlugin> binding : pluginManager.getResolver().getResolvedPlugins()) {
try {
binding.getPlugin().prepareTestInstance(this);
} catch (Exception e) {
throw new TestPluginException(e, "An error occured while executing 'prepareTestInstance' on plugin '%s': %s: %s", binding.getName(), e.getClass().getSimpleName(), e.getMessage());
}
}
} finally {
Mycila.unsetCurrentExecution();
}
}
public void fireBeforeTest(Method method) throws TestPluginException {
notNull("Test method", method);
TestExecutionImpl testExecution = new TestExecutionImpl(this, method);
try {
Mycila.registerCurrentExecution(testExecution.changeStep(Step.BEFORE));
LOGGER.debug("Calling 'beforeTest' on plugins for test %s#%s...", introspector.testClass().getName(), introspector.instance().hashCode());
for (PluginBinding<TestPlugin> binding : pluginManager.getResolver().getResolvedPlugins()) {
try {
binding.getPlugin().beforeTest(testExecution);
} catch (Exception e) {
throw new TestPluginException(e, "An error occured while executing 'beforeTest' on plugin '%s': %s: %s", binding.getName(), e.getClass().getSimpleName(), e.getMessage());
}
}
} finally {
Mycila.unsetCurrentExecution();
Mycila.registerCurrentExecution(testExecution.changeStep(Step.TEST));
}
}
public void fireAfterTest() throws TestPluginException {
try {
TestExecutionImpl testExecution = (TestExecutionImpl) Mycila.currentExecution();
Mycila.unsetCurrentExecution();
Mycila.registerCurrentExecution(testExecution.changeStep(Step.AFTER));
LOGGER.debug("Calling 'afterTest' on plugins for test %s#%s...", introspector.testClass().getName(), introspector.instance().hashCode());
for (PluginBinding<TestPlugin> binding : pluginManager.getResolver().getResolvedPlugins()) {
try {
binding.getPlugin().afterTest(testExecution);
} catch (Exception e) {
throw new TestPluginException(e, "An error occured while executing 'afterTest' on plugin '%s': %s: %s", binding.getName(), e.getClass().getSimpleName(), e.getMessage());
}
}
} finally {
Mycila.unsetCurrentExecution();
}
}
public void fireAfterClass() throws TestPluginException {
try {
ExecutionImpl execution = new ExecutionImpl(this, fireAfterClassMethod);
Mycila.registerCurrentExecution(execution.changeStep(Step.COMPLETED));
LOGGER.debug("Calling 'afterClass' on plugins for test %s#%s...", introspector.testClass().getName(), introspector.instance().hashCode());
for (PluginBinding<TestPlugin> binding : pluginManager.getResolver().getResolvedPlugins()) {
try {
binding.getPlugin().afterClass(this);
} catch (Exception e) {
throw new TestPluginException(e, "An error occured while executing 'afterClass' on plugin '%s': %s: %s", binding.getName(), e.getClass().getSimpleName(), e.getMessage());
}
}
} finally {
Mycila.unsetCurrentExecution();
}
}
public void shutdown() {
try {
ExecutionImpl execution = new ExecutionImpl(this, shutdownMethod);
Mycila.registerCurrentExecution(execution.changeStep(Step.SHUTDOWN));
LOGGER.debug("Calling 'shutdown' on plugins for test %s#%s...", introspector.testClass().getName(), introspector.instance().hashCode());
for (PluginBinding<TestPlugin> binding : pluginManager.getResolver().getResolvedPlugins()) {
try {
binding.getPlugin().shutdown(this);
} catch (Exception e) {
LOGGER.error(e, "An error occured while executing 'shutdown' on plugin %s: %s: %s", binding.getName(), e.getClass().getSimpleName(), e.getMessage());
}
}
} finally {
Mycila.unsetCurrentExecution();
Mycila.unsetContext(this);
}
}
}