package net.sourceforge.cobertura.webapp.test;
import static org.junit.Assert.*;
import groovy.util.Node;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import net.sourceforge.cobertura.ant.InstrumentTask;
import net.sourceforge.cobertura.ant.ReportTask;
import net.sourceforge.cobertura.test.util.TestUtils;
import net.sourceforge.cobertura.webapp.FlushCoberturaServlet;
import org.apache.commons.io.FileUtils;
import org.apache.tools.ant.taskdefs.Javac;
import org.apache.tools.ant.taskdefs.War;
import org.apache.tools.ant.taskdefs.Zip;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.ZipFileSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mortbay.jetty.testing.HttpTester;
import org.mortbay.jetty.testing.ServletTester;
/**
*
* This test tests the functional FlushCoberturaServlet used for jetty sevlets.
*
* We use the ServletTester API to remove the sensitive tests that were in
* the previous versions of cobertura.
*
* @author schristou88
*
*/
public class WebAppFunctionalTest {
ServletTester tester;
HttpTester request;
HttpTester response;
File tempDir = TestUtils.getTempDir();
public static final String SIMPLE_SERVLET_CLASSNAME = "com.acme.servlet.SimpleServlet";
private static final String SAVE_DATA_METHOD_NAME = "doGet";
@Before
public void setUp() throws Exception {
FileUtils.deleteDirectory(tempDir);
FileUtils.deleteQuietly(new File("cobertura.ser"));
FileUtils.deleteQuietly(new File(tempDir.getAbsolutePath(),
"coverage.xml"));
}
@After
public void tearDown() throws Exception {
if (tester != null)
tester.stop();
}
@Test
public void testServletCreation() throws Exception {
startUpServlet();
pingServer();
}
@Test
public void testCoberturaServlet() throws Exception {
startUpServlet();
pingCoberturaServer();
}
@Test
public void testFlushCoberturaData() throws Exception {
createSimpleWar();
createCoberturaServlet();
createCoberturaJar();
instrumentWar();
startUpServlet();
pingServer();
generateReportFile();
Node dom = TestUtils.getXMLReportDOM(new File(
tempDir.getAbsolutePath(), "coverage.xml"));
int hitCountBefore = TestUtils.getHitCount(dom,
SIMPLE_SERVLET_CLASSNAME, SAVE_DATA_METHOD_NAME);
assertEquals(0, hitCountBefore);
pingCoberturaServer();
generateReportFile();
dom = TestUtils.getXMLReportDOM(new File(tempDir.getAbsolutePath(),
"coverage.xml"));
int hitCountAfter = TestUtils.getHitCount(dom,
SIMPLE_SERVLET_CLASSNAME, SAVE_DATA_METHOD_NAME);
tester.stop();
assertEquals("Hit count should have increased by one",
hitCountBefore + 1, hitCountAfter);
}
@Test
public void testFlushCoberturaData2() throws Exception {
createSimpleWar();
createCoberturaServlet();
createCoberturaJar();
instrumentWar();
startUpServlet();
pingServer();
generateReportFile();
Node dom = TestUtils.getXMLReportDOM(new File(
tempDir.getAbsolutePath(), "coverage.xml"));
int hitCountBefore = TestUtils.getHitCount(dom,
SIMPLE_SERVLET_CLASSNAME, SAVE_DATA_METHOD_NAME);
assertEquals(0, hitCountBefore);
pingCoberturaServer();
generateReportFile();
dom = TestUtils.getXMLReportDOM(new File(tempDir.getAbsolutePath(),
"coverage.xml"));
int hitCountAfter = TestUtils.getHitCount(dom,
SIMPLE_SERVLET_CLASSNAME, SAVE_DATA_METHOD_NAME);
assertEquals(2, hitCountAfter);
tester.stop();
generateReportFile();
dom = TestUtils.getXMLReportDOM(new File(tempDir.getAbsolutePath(),
"coverage.xml"));
int hitCountFinal = TestUtils.getHitCount(dom,
SIMPLE_SERVLET_CLASSNAME, SAVE_DATA_METHOD_NAME);
assertEquals(hitCountAfter, hitCountFinal);
}
@Test
public void testFlushCoberturaDataOnly() throws Exception {
createSimpleWar();
createCoberturaServlet();
createCoberturaJar();
instrumentWar();
startUpServlet();
generateReportFile();
Node dom = TestUtils.getXMLReportDOM(new File(
tempDir.getAbsolutePath(), "coverage.xml"));
int hitCountBefore = TestUtils.getHitCount(dom,
SIMPLE_SERVLET_CLASSNAME, SAVE_DATA_METHOD_NAME);
assertEquals(0, hitCountBefore);
generateReportFile();
dom = TestUtils.getXMLReportDOM(new File(tempDir.getAbsolutePath(),
"coverage.xml"));
int hitCountAfter = TestUtils.getHitCount(dom,
SIMPLE_SERVLET_CLASSNAME, SAVE_DATA_METHOD_NAME);
assertEquals(0, hitCountAfter);
tester.stop();
generateReportFile();
dom = TestUtils.getXMLReportDOM(new File(tempDir.getAbsolutePath(),
"coverage.xml"));
int finalCount = TestUtils.getHitCount(dom, SIMPLE_SERVLET_CLASSNAME,
SAVE_DATA_METHOD_NAME);
assertEquals(0, finalCount);
}
public void startUpServlet() throws Exception {
tester = new ServletTester();
request = new HttpTester();
response = new HttpTester();
ClassLoader loader = createClassLoader();
tester.setClassLoader(loader);
tester.addServlet("com.acme.servlet.SimpleServlet",
"/simple/SimpleServlet");
tester.addServlet(FlushCoberturaServlet.class,
"/coberturaFlush/flushCobertura");
tester.start();
request.setMethod("GET");
request.setHeader("host", "tester");
request.setVersion("HTTP/1.0");
}
public void pingServer() throws Exception {
request.setURI("/simple/SimpleServlet");
response.parse(tester.getResponses(request.generate()));
assertNull(response.getMethod());
assertEquals(200, response.getStatus());
assertEquals("Hi", response.getContent().trim());
}
public void pingCoberturaServer() throws Exception {
request.setURI("/coberturaFlush/flushCobertura");
response.parse(tester.getResponses(request.generate()));
assertNull(response.getMethod());
assertEquals(200, response.getStatus());
assertNull(response.getContent());
}
private void createSimpleWar() throws IOException {
File webappsDir = new File(tempDir, "webapps");
File war = new File(webappsDir, "simple.war");
File classesDir = new File("target/build/simpleWarClasses/");
if (!classesDir.exists())
classesDir.mkdirs();
FileUtils.copyDirectory(new File("target/test-classes/com"), new File(
classesDir, "com"));
War antWar = new War();
antWar.setProject(TestUtils.project);
antWar.setDestFile(war);
antWar.setWebxml(new File("src/test/resources/testJetty/web.xml"));
ZipFileSet classesFileSet = new ZipFileSet();
classesFileSet.setDir(classesDir);
antWar.addClasses(classesFileSet);
antWar.execute();
}
private void createCoberturaServlet() {
File webappsDir = new File(TestUtils.getTempDir(), "webapps");
File war = new File(webappsDir, "coberturaFlush.war");
File classesDir = new File("target/build/warClasses");
if (!classesDir.exists())
classesDir.mkdirs();
Javac javac = new Javac();
javac.setProject(TestUtils.project);
javac.setSrcdir(new Path(TestUtils.project, "src/main/java"));
javac.setDestdir(classesDir);
javac.setDebug(true);
Path classpath = new Path(TestUtils.project);
FileSet jettyFileSet = new FileSet();
jettyFileSet.setDir(new File("src/test/resources/jetty"));
jettyFileSet.setIncludes("**/*.jar");
classpath.addFileset(jettyFileSet);
javac.setIncludes("**/FlushCoberturaServlet.java");
javac.setClasspath(classpath);
javac.execute();
War antWar = new War();
antWar.setProject(TestUtils.project);
antWar.setDestFile(war);
antWar.setWebxml(new File(
"src/main/java/net/sourceforge/cobertura/webapp/web.xml"));
ZipFileSet classesFileSet = new ZipFileSet();
classesFileSet.setDir(classesDir);
antWar.addClasses(classesFileSet);
antWar.execute();
}
private ClassLoader createClassLoader() throws Exception {
File simplewar = new File(tempDir, "webapps/simple.war");
File coberturawar = new File(tempDir, "webapps/coberturaFlush.war");
File coberturaJar = new File(tempDir, "lib/cobertura.jar");
@SuppressWarnings("deprecation")
URL[] urls = new URL[]{simplewar.toURL(), coberturawar.toURL(),
coberturaJar.toURL()};
System.out.println(Arrays.toString(urls));
// Create a new class loader with the directory
return new URLClassLoader(urls);
}
private void createCoberturaJar() {
File coberturaJar = new File(tempDir, "lib/cobertura.jar");
File coberturaClassDir = TestUtils.getCoberturaClassDir();
Zip zip = new Zip();
zip.setProject(TestUtils.project);
zip.setDestFile(coberturaJar);
FileSet fileSet = new FileSet();
fileSet.setDir(coberturaClassDir);
zip.addFileset(fileSet);
zip.execute();
}
private void instrumentWar() {
instrumentWar(new File(tempDir, "webapps/simple.war"));
// Future: There is an issue with ServetTester api and adding a custom classloader.
// When specify the instrumented .war file it still prefers to use the
// target/test-classes/**/*.class files instead. In this situation we instrument the
// classes directly but a better solution should be provided for this.
instrumentClasses(new File(
"target/test-classes/com/acme/servlet/SimpleServlet.class"));
}
private void instrumentClasses(File classesDir) {
InstrumentTask instrumentTask = new InstrumentTask();
instrumentTask.setProject(TestUtils.project);
instrumentTask.setDataFile("cobertura.ser");
FileSet fileSet = new FileSet();
fileSet.setDir(classesDir.getParentFile());
fileSet.setIncludes("**/*.class");
instrumentTask.addFileset(fileSet);
instrumentTask.execute();
}
private void instrumentWar(File warFile) {
InstrumentTask instrumentTask = new InstrumentTask();
instrumentTask.setProject(TestUtils.project);
instrumentTask.setDataFile("cobertura.ser");
FileSet fileSet = new FileSet();
fileSet.setDir(warFile.getParentFile());
fileSet.setIncludes("**/*.war");
instrumentTask.addFileset(fileSet);
instrumentTask.execute();
}
public void generateReportFile() {
File xmlReport = new File(tempDir.getAbsolutePath(), "coverage.xml");
ReportTask reportTask = new ReportTask();
reportTask.setProject(TestUtils.project);
reportTask.setDataFile("cobertura.ser");
reportTask.setFormat("xml");
reportTask.setDestDir(new File(xmlReport.getParent()));
reportTask.execute();
}
}