package org.pitest.coverage;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.instrument.IllegalClassFormatException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.util.ASMifier;
import org.objectweb.asm.util.CheckClassAdapter;
import org.objectweb.asm.util.TraceClassVisitor;
import org.pitest.classinfo.ClassByteArraySource;
import org.pitest.classpath.ClassloaderByteArraySource;
import org.pitest.classpath.OtherClassLoaderClassPathRoot;
import org.pitest.functional.predicate.False;
import org.pitest.functional.predicate.True;
import org.pitest.util.IsolationUtils;
import org.pitest.util.StreamUtil;
import sun.pitest.CodeCoverageStore;
import sun.pitest.InvokeReceiver;
public class CoverageTransformerTest {
private final ClassLoader loader = IsolationUtils
.getContextClassLoader();
private final ClassByteArraySource bytes = new ClassloaderByteArraySource(
this.loader);
@Mock
private InvokeReceiver invokeQueue;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
CodeCoverageStore.init(this.invokeQueue);
}
@After
public void tearDown() {
CodeCoverageStore.resetAllStaticState();
}
@Test
public void shouldNotTransformClassesNotMatchingPredicate()
throws IllegalClassFormatException {
final CoverageTransformer testee = new CoverageTransformer(
False.<String> instance());
assertNull(testee.transform(null, "anything", null, null, null));
}
@Test
public void shouldTransformClasseMatchingPredicate()
throws IllegalClassFormatException {
final CoverageTransformer testee = new CoverageTransformer(
True.<String> all());
final byte[] bs = this.bytes.getBytes(String.class.getName()).value();
assertFalse(Arrays.equals(bs,
testee.transform(null, "anything", null, null, bs)));
}
@Test
public void shouldGenerateValidClasses() throws IllegalClassFormatException {
assertValidClass(String.class);
assertValidClass(Integer.class);
assertValidClass(Vector.class);
assertValidClass(ArrayList.class);
assertValidClass(Collections.class);
assertValidClass(ConcurrentHashMap.class);
assertValidClass(Math.class);
}
private void assertValidClass(final Class<?> clazz)
throws IllegalClassFormatException {
final byte[] bs = transform(clazz);
// printClass(bs);
final StringWriter sw = new StringWriter();
CheckClassAdapter.verify(new ClassReader(bs), false, new PrintWriter(sw));
assertTrue(sw.toString(), sw.toString().length() == 0);
}
protected void printRaw(final Class<?> clazz) throws IOException {
OtherClassLoaderClassPathRoot r = new OtherClassLoaderClassPathRoot(
IsolationUtils.getContextClassLoader());
printClass(StreamUtil.streamToByteArray(r.getData(clazz.getName())));
}
protected void printClass(final byte[] bs) {
final ClassReader reader = new ClassReader(bs);
reader.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(
System.out)), ClassReader.EXPAND_FRAMES);
}
private byte[] transform(final Class<?> clazz)
throws IllegalClassFormatException {
final CoverageTransformer testee = new CoverageTransformer(
True.<String> all());
final byte[] bs = testee.transform(this.loader, clazz.getName(), null,
null, this.bytes.getBytes(clazz.getName()).value());
return bs;
}
}