// Copyright (c) 2002-2005 Canoo Engineering AG, Switzerland.
package com.canoo.webtest.reporting;
import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import junit.framework.TestCase;
import org.apache.log4j.Logger;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;
import com.canoo.webtest.ant.TestStepSequence;
import com.canoo.webtest.ant.WebtestTask;
import com.canoo.webtest.engine.Configuration;
import com.canoo.webtest.engine.Context;
import com.canoo.webtest.engine.DefaultWebtestCustomizer;
import com.canoo.webtest.interfaces.IComputeValue;
import com.canoo.webtest.steps.Step;
/**
* Unit tests for {@link StepExecutionListener}.
* @author Unknown
* @author Marc Guillemot
* @author Ardeshir Arfaian
*/
public class StepExecutionListenerTest extends TestCase {
private static final Logger LOG = Logger.getLogger(StepExecutionListenerTest.class);
public static class StringBufferReporter implements IResultReporter
{
static Map<String, String> reports = Collections.synchronizedMap(new HashMap<String, String>());
public void generateReport(final RootStepResult result) throws IOException {
final StringBuilder sb = new StringBuilder();
for (final StepResult res : result.getChildren())
{
sb.append(res.getTaskName() + ":" + res.getAttributes() + "\n");
}
reports.put(result.getWebtestName(), sb.toString());
}
}
/**
* Task that waits until the "status" has reached
* the given state to increase it by 1.
*/
public static class WaitingTask extends Step
{
private static final long serialVersionUID = 4919608524778827568L;
public static int currentState = 1;
private final int state;
WaitingTask(final int _state, final Project _project)
{
state = _state;
setProject(_project);
}
@Override
public void doExecute() throws Exception {
for (int i=0; i<10; ++i)
{
synchronized (WaitingTask.class)
{
if (currentState < state)
{
try {
WaitingTask.class.wait(100);
}
catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
else
{
currentState = state + 1;
WaitingTask.class.notifyAll();
}
}
}
}
/**
* Don't rely on {link {@link IComputeValue#getComputedValue()} for this
* test as all results will have the same key and no synchronization issue
* will occur
*/
@Override
protected void addComputedParameters(final Map map) {
map.put(getTaskName(), state);
}
public String getComputedValue() {
return "compute value for " + state;
}
@Override
public String getTaskName() {
return "wait" + state;
}
}
/**
* Test that only the right result listener gets its results when tests run in parallel
* @see <a href="http://webtest-community.canoo.com/jira/browse/WT-477">WT-477</a>
*/
public void testParallelUse() throws Exception
{
final Project project = new Project();
final String reporterClassName = StringBufferReporter.class.getName();
project.setProperty(WebtestTask.REPORTER_CLASSNAME_PROPERTY, reporterClassName);
assertEquals(reporterClassName, project.getProperty(WebtestTask.REPORTER_CLASSNAME_PROPERTY));
final WebtestTask webtest1 = new WebtestTask();
webtest1.setName("test 1");
webtest1.setProject(project);
webtest1.addTask(new WaitingTask(1, project));
webtest1.addTask(new WaitingTask(3, project));
final WebtestTask webtest2 = new WebtestTask();
webtest2.setName("test 2");
webtest2.setProject(project);
webtest2.addTask(new WaitingTask(2, project));
webtest2.addTask(new WaitingTask(4, project));
final Thread thread1 = new Thread("WebTest1")
{
@Override
public void run() {
webtest1.execute();
}
};
final Thread thread2 = new Thread("WebTest2")
{
@Override
public void run() {
webtest2.execute();
}
};
final List<Throwable> uncaugtExceptions = new ArrayList<Throwable>();
final UncaughtExceptionHandler collectingExceptionHandler = new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread t, Throwable e) {
LOG.error(e);
uncaugtExceptions.add(e);
}
};
thread1.setUncaughtExceptionHandler(collectingExceptionHandler);
thread1.start();
thread2.setUncaughtExceptionHandler(collectingExceptionHandler);
thread2.start();
thread2.join(5000);
thread1.join(5000);
if (!uncaugtExceptions.isEmpty())
{
uncaugtExceptions.get(0).printStackTrace(System.err);
assertTrue("Found exceptions: " + uncaugtExceptions, uncaugtExceptions.isEmpty());
}
assertEquals("wait1:{wait1=1}\nwait3:{wait3=3}\n", StringBufferReporter.reports.get("test 1"));
assertEquals("wait2:{wait2=2}\nwait4:{wait4=4}\n", StringBufferReporter.reports.get("test 2"));
}
private class DummyStepExecutionListener extends StepExecutionListener {
private boolean isWebtestFinishedInvoked;
public DummyStepExecutionListener(Context context) {
super(context);
isWebtestFinishedInvoked = false;
}
public void webtestFinished() {
isWebtestFinishedInvoked = true;
}
public boolean isWebtestFinishedInvoked() {
return isWebtestFinishedInvoked;
}
}
public void testAllMethodsInvoked() {
Project project = new Project();
WebtestTask webTest = new WebtestTask();
webTest.setProject(project);
webTest.setName("TestWebTest");
Configuration config = new Configuration(webTest);
Context context = new Context(webTest);
config.setProject(project);
config.setContext(context);
class DummyCustomizerImpl extends DefaultWebtestCustomizer {
private DummyStepExecutionListener dummyListener;
public StepExecutionListener createExecutionListener(WebtestTask wt) {
return dummyListener = new DummyStepExecutionListener(wt.getConfig().getContext());
}
public DummyStepExecutionListener getDummyListener() {
return dummyListener;
}
};
DummyCustomizerImpl dummyCustomizer = new DummyCustomizerImpl();
project.addReference("wt.webtestCustomizer", dummyCustomizer);
webTest.setProject(project);
final TestStepSequence steps = new TestStepSequence();
steps.setProject(project);
webTest.addSteps(steps);
Target target = new Target();
target.setProject(project);
webTest.setOwningTarget(target);
webTest.execute();
assertNotNull(dummyCustomizer.getDummyListener());
assertTrue(dummyCustomizer.getDummyListener().isWebtestFinishedInvoked());
}
}