/*
* Copyright 2012 Henry Coles
*
* 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 org.pitest.coverage;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.pitest.coverage.CoverageMother.aBlockLocation;
import static org.pitest.coverage.CoverageMother.aCoverageResult;
import static org.pitest.mutationtest.LocationMother.aLocation;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.pitest.classinfo.ClassInfo;
import org.pitest.classinfo.ClassInfoMother;
import org.pitest.classinfo.ClassName;
import org.pitest.classpath.CodeSource;
import org.pitest.coverage.CoverageMother.BlockLocationBuilder;
import org.pitest.coverage.CoverageMother.CoverageResultBuilder;
import org.pitest.functional.F;
import org.pitest.functional.FCollection;
import org.pitest.mutationtest.engine.Location;
import org.pitest.mutationtest.engine.MethodName;
import org.pitest.testapi.Description;
public class CoverageDataTest {
private CoverageData testee;
@Mock
private CodeSource code;
@Mock
private LineMap lm;
private final ClassName foo = ClassName.fromString("foo");
private final ClassName bar = ClassName.fromString("bar");
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(this.lm.mapLines(any(ClassName.class))).thenReturn(
new HashMap<BlockLocation, Set<Integer>>());
this.testee = new CoverageData(this.code, this.lm);
}
@Test
public void shouldReturnNoTestsWhenNoTestsCoverALine() {
when(this.lm.mapLines(any(ClassName.class))).thenReturn(
new HashMap<BlockLocation, Set<Integer>>());
final ClassLine line = new ClassLine("foo", 1);
assertEquals(Collections.emptyList(),
this.testee.getTestsForClassLine(line));
}
@Test
public void shouldStoreExecutionTimesOfTests() {
int line = 1;
int time = 42;
BlockLocationBuilder block = aBlockLocation().withLocation(
aLocation().withClass(this.foo));
when(this.lm.mapLines(any(ClassName.class))).thenReturn(
makeCoverageMapForBlock(block, line));
CoverageResultBuilder cr = aCoverageResult().withVisitedBlocks(
block.build(1)).withExecutionTime(time);
this.testee.calculateClassCoverage(cr.build());
assertEquals(Arrays.asList(42), FCollection.map(
this.testee.getTestsForClassLine(new ClassLine(this.foo, line)),
testInfoToExecutionTime()));
}
@Test
public void shouldReportNumberOfCoveredLinesWhenNoneCovered() {
assertEquals(0, this.testee.getNumberOfCoveredLines(Collections
.singletonList(ClassName.fromString("foo"))));
}
@Test
public void shouldReportNumberOfCoveredLinesWhenSomeCovered() {
BlockLocationBuilder block = aBlockLocation().withLocation(
aLocation().withClass(this.foo));
when(this.lm.mapLines(any(ClassName.class))).thenReturn(
makeCoverageMapForBlock(block, 101, 300));
CoverageResultBuilder cr = aCoverageResult().withVisitedBlocks(
block.build(1));
this.testee.calculateClassCoverage(cr.build());
assertEquals(2, this.testee.getNumberOfCoveredLines(Collections
.singletonList(this.foo)));
}
@Test
public void shouldReturnNotTestsWhenNoTestsCoverClass() {
assertTrue(this.testee.getTestsForClass(this.foo).isEmpty());
}
@Test
public void shouldReturnUniqueTestsForClassWhenSomeTestsCoverClass() {
this.testee.calculateClassCoverage(makeCoverageResult("foo", "fooTest", 0,
1));
this.testee.calculateClassCoverage(makeCoverageResult("foo", "fooTest", 0,
2));
this.testee.calculateClassCoverage(makeCoverageResult("foo", "fooTest2", 0,
2));
assertEquals(Arrays.asList("fooTest", "fooTest2"), FCollection.map(
this.testee.getTestsForClass(this.foo), testInfoToString()));
}
@Test
public void shouldReportAGreenSuiteWhenNoTestHasFailed() {
this.testee.calculateClassCoverage(makeCoverageResult("foo", "fooTest", 42,
1));
assertTrue(this.testee.allTestsGreen());
}
@Test
public void shouldNotReportAGreenSuiteWhenATestHasFailed() {
this.testee.calculateClassCoverage(makeCoverageResult("foo",
new Description("fooTest"), 42, 1, false));
assertFalse(this.testee.allTestsGreen());
}
@Test
public void shouldProvideAccessToClassData() {
final Collection<ClassName> classes = Arrays.asList(ClassName
.fromString("foo"));
this.testee.getClassInfo(classes);
verify(this.code).getClassInfo(classes);
}
@Test
public void shouldReturnCoverageIdOf0WhenNoTestsCoverClass() {
assertEquals(0,
this.testee.getCoverageIdForClass(ClassName.fromString("unknown"))
.longValue());
}
@SuppressWarnings("unchecked")
@Test
public void shouldReturnNonZeroCoverageIdWhenTestsCoverClass() {
final ClassName foo = ClassName.fromString("Foo");
final ClassInfo ci = ClassInfoMother.make(foo);
when(this.code.getClassInfo(any(Collection.class))).thenReturn(
Collections.singletonList(ci));
BlockLocationBuilder block = aBlockLocation().withLocation(
aLocation().withClass(foo));
HashMap<BlockLocation, Set<Integer>> map = makeCoverageMapForBlock(block,
42);
when(this.lm.mapLines(any(ClassName.class))).thenReturn(map);
this.testee.calculateClassCoverage(aCoverageResult().withVisitedBlocks(
block.build(1)).build());
assertThat(this.testee.getCoverageIdForClass(foo).longValue())
.isNotEqualTo(0);
}
@Test
public void shouldProvideEmptyBlockCoverageListWhenNoCoverage() {
assertEquals(Collections.emptyList(), this.testee.createCoverage());
}
@Test
public void shouldProvideCoverageListWhenCoverageRecorded() {
BlockLocationBuilder block = aBlockLocation().withLocation(
aLocation().withClass(this.foo));
CoverageResultBuilder cr = aCoverageResult().withVisitedBlocks(
block.build(1));
this.testee.calculateClassCoverage(cr.build());
this.testee.calculateClassCoverage(makeCoverageResult("foo", "fooTest", 0,
1));
final BlockCoverage actual = this.testee.createCoverage().get(0);
assertEquals(block.build(), actual.getBlock());
assertThat(actual.getTests()).contains("FooTest.fooTest");
}
@Test
public void shouldProvideListOfClassesForSourceFile() {
final ClassInfo fooClass = ClassInfoMother.make(this.foo, "foo.java");
final ClassInfo barClass = ClassInfoMother.make(this.bar, "bar.java");
final Collection<ClassInfo> classes = Arrays.asList(fooClass, barClass);
when(this.code.getCode()).thenReturn(classes);
this.testee = new CoverageData(this.code, this.lm);
assertEquals(Arrays.asList(barClass),
this.testee.getClassesForFile("bar.java", ""));
}
@Test
public void shouldMatchPackageWhenFindingSources() {
final ClassName foo1 = ClassName.fromString("a.b.c.foo");
final ClassName foo2 = ClassName.fromString("d.e.f.foo");
final ClassInfo foo1Class = ClassInfoMother.make(foo1, "foo.java");
final ClassInfo foo2Class = ClassInfoMother.make(foo2, "foo.java");
final Collection<ClassInfo> classes = Arrays.asList(foo1Class, foo2Class);
when(this.code.getCode()).thenReturn(classes);
this.testee = new CoverageData(this.code, this.lm);
assertEquals(Arrays.asList(foo1Class),
this.testee.getClassesForFile("foo.java", "a.b.c"));
}
@Test
public void shouldIncludeAllCoveredLinesInCoverageSummary() {
BlockLocationBuilder block = aBlockLocation();
when(this.code.getCodeUnderTestNames()).thenReturn(
Collections.singleton(block.build().getLocation().getClassName()));
when(this.lm.mapLines(any(ClassName.class))).thenReturn(
makeCoverageMapForBlock(block, 1, 2, 3, 4));
CoverageResultBuilder cr = aCoverageResult().withVisitedBlocks(
block.build(1));
this.testee.calculateClassCoverage(cr.build());
CoverageSummary actual = this.testee.createSummary();
assertEquals(4, actual.getNumberOfCoveredLines());
}
private static F<TestInfo, Integer> testInfoToExecutionTime() {
return new F<TestInfo, Integer>() {
@Override
public Integer apply(final TestInfo a) {
return a.getTime();
}
};
}
private static F<TestInfo, String> testInfoToString() {
return new F<TestInfo, String>() {
@Override
public String apply(final TestInfo a) {
return a.getName();
}
};
}
private CoverageResult makeCoverageResult(final String clazz,
final String testName, final int time, final int block) {
return makeCoverageResult(clazz, new Description(testName), time, block,
true);
}
private CoverageResult makeCoverageResult(final String clazz,
final Description desc, final int time, final int block,
final boolean testPassed) {
return new CoverageResult(desc, time, testPassed,
makeCoverage(clazz, block));
}
private Collection<BlockLocation> makeCoverage(final String clazz,
final int block) {
final BlockLocation cs = new BlockLocation(Location.location(
ClassName.fromString(clazz), MethodName.fromString("foo"), "V"), block);
return Collections.singleton(cs);
}
private HashMap<BlockLocation, Set<Integer>> makeCoverageMapForBlock(
BlockLocationBuilder blocks, Integer... lines) {
HashMap<BlockLocation, Set<Integer>> map = new HashMap<BlockLocation, Set<Integer>>();
Set<Integer> s = new HashSet<Integer>();
s.addAll(Arrays.asList(lines));
map.put(blocks.build(), s);
return map;
}
}