package com.ikokoon.serenity.instrumentation.coverage; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.junit.Before; import org.junit.Test; import org.objectweb.asm.ClassWriter; import com.ikokoon.serenity.ATest; import com.ikokoon.serenity.instrumentation.VisitorFactory; import com.ikokoon.serenity.model.Line; public class CoverageTest extends ATest { // private IDataBase dataBase; @Before public void clear() { // dataBase = IDataBase.DataBaseManager.getDataBase(DataBaseRam.class, IConstants.DATABASE_FILE_RAM, mockInternalDataBase); // DataBaseToolkit.clear(dataBase); // Collector.initialize(dataBase); } @Test @SuppressWarnings("unchecked") public void visit() throws Exception { byte[] classBytes = getClassBytes(className); byte[] sourceBytes = getSourceBytes(className); // Verify that the coverage instructions are not in the byte code Exception exception = null; try { visitClass(CoverageClassAdapterChecker.class, className, classBytes, sourceBytes); } catch (Exception e) { logger.error("Expected exception : " + e.getMessage() + ", " + e); exception = e; } assertNotNull(exception); // Add the coverage instructions ByteArrayOutputStream source = new ByteArrayOutputStream(); source.write(sourceBytes); ClassWriter writer = (ClassWriter) VisitorFactory.getClassVisitor(new Class[] { CoverageClassAdapter.class }, className, classBytes, source); classBytes = writer.toByteArray(); // File file = new File(className + ".class"); // if (!file.exists()) { // file.createNewFile(); // } // Toolkit.setContents(file, classBytes); // Verify the byte code is valid, only for ASM 3++ // CheckClassAdapter.verify(new ClassReader(classBytes), false, new PrintWriter(System.out)); // Verify each line has a call to collect the coverage visitClass(CoverageClassAdapterChecker.class, className, classBytes, sourceBytes); final byte[] finalClassBytes = classBytes; final String finalClassName = className; // Call the complex method on the target and verify that the Collector was called with the new ClassLoader loader = new ClassLoader() { public Class loadClass(String className) throws ClassNotFoundException { if (className == finalClassName) { return this.defineClass(className, finalClassBytes, 0, finalClassBytes.length); } return super.loadClass(className); } }; Thread.currentThread().setContextClassLoader(loader); Object target = loader.loadClass(className).newInstance(); Method method = target.getClass().getDeclaredMethod("complexMethod", new Class[] { String.class, String.class, String.class, Integer.class, Integer.class }); method.invoke(target, new Object[] { "", "", "", 0, 0 }); // Now verify that the Collector class was called from the added instructions List<Object> parameters = new ArrayList<Object>(); parameters.add(className); parameters.add(methodName); parameters.add(96d); Line<?, ?> line = (Line) dataBase.find(Line.class, parameters); assertNotNull(line); assertTrue(line.getCounter() > 0); } }