1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.eluder.coveralls.maven.plugin.parser;
25
26 import static org.junit.jupiter.api.Assertions.assertNull;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import static org.junit.jupiter.api.Assertions.fail;
29 import static org.mockito.Mockito.atLeast;
30 import static org.mockito.Mockito.lenient;
31 import static org.mockito.Mockito.verify;
32
33 import java.io.File;
34 import java.io.IOException;
35 import java.security.NoSuchAlgorithmException;
36 import java.util.ArrayList;
37 import java.util.Collection;
38 import java.util.Collections;
39 import java.util.HashSet;
40 import java.util.List;
41 import java.util.Set;
42
43 import org.eluder.coveralls.maven.plugin.CoverageFixture;
44 import org.eluder.coveralls.maven.plugin.CoverageParser;
45 import org.eluder.coveralls.maven.plugin.ProcessingException;
46 import org.eluder.coveralls.maven.plugin.domain.Branch;
47 import org.eluder.coveralls.maven.plugin.domain.Source;
48 import org.eluder.coveralls.maven.plugin.source.ChainingSourceCallback;
49 import org.eluder.coveralls.maven.plugin.source.SourceCallback;
50 import org.eluder.coveralls.maven.plugin.source.SourceLoader;
51 import org.eluder.coveralls.maven.plugin.source.UniqueSourceCallback;
52 import org.eluder.coveralls.maven.plugin.util.TestIoUtil;
53 import org.junit.jupiter.api.BeforeEach;
54 import org.junit.jupiter.api.Test;
55 import org.junit.jupiter.api.extension.ExtendWith;
56 import org.mockito.ArgumentCaptor;
57 import org.mockito.Mock;
58 import org.mockito.invocation.InvocationOnMock;
59 import org.mockito.junit.jupiter.MockitoExtension;
60 import org.mockito.stubbing.Answer;
61
62 @ExtendWith(MockitoExtension.class)
63 public abstract class AbstractCoverageParserTest {
64
65 @Mock
66 protected SourceLoader sourceLoaderMock;
67
68 @Mock
69 protected SourceCallback sourceCallbackMock;
70
71 @BeforeEach
72 public void init() throws IOException {
73 for (String[] coverageFile : getCoverageFixture()) {
74 final String name = sourceName(coverageFile[0]);
75 final String content = TestIoUtil.readFileContent(TestIoUtil.getFile(name));
76 lenient().when(sourceLoaderMock.load(name)).then(sourceAnswer(name, content));
77 }
78 }
79
80 protected String sourceName(final String coverageFile) {
81 return coverageFile;
82 }
83
84 protected Answer<Source> sourceAnswer(final String name, final String content) {
85 return new Answer<Source>() {
86 @Override
87 public Source answer(final InvocationOnMock invocation) throws NoSuchAlgorithmException {
88 return new Source(name, content, TestIoUtil.getSha512DigestHex(content));
89 }
90 };
91 }
92
93 @Test
94 public void testParseCoverage() throws ProcessingException, IOException {
95 for (String coverageResource : getCoverageResources()) {
96 CoverageParser parser = createCoverageParser(TestIoUtil.getFile(coverageResource), sourceLoaderMock);
97 parser.parse(sourceCallbackMock);
98 }
99
100 String[][] fixture = getCoverageFixture();
101
102 ArgumentCaptor<Source> captor = ArgumentCaptor.forClass(Source.class);
103 verify(sourceCallbackMock, atLeast(CoverageFixture.getTotalFiles(fixture))).onSource(captor.capture());
104
105 SourceCollector sourceCollector = new SourceCollector();
106 UniqueSourceCallback uniqueSourceCallback = new UniqueSourceCallback(sourceCollector);
107 ClassifierRemover classifierRemover = new ClassifierRemover(uniqueSourceCallback);
108 classifierRemover.onBegin();
109 for (Source source: captor.getAllValues()) {
110 classifierRemover.onSource(source);
111 }
112 classifierRemover.onComplete();
113
114 for (String[] coverageFile : fixture) {
115 assertCoverage(sourceCollector.sources, coverageFile[0], Integer.parseInt(coverageFile[1]),
116 toIntegerSet(coverageFile[2]), toIntegerSet(coverageFile[3]),
117 toIntegerSet(coverageFile[4]), toIntegerSet(coverageFile[5]));
118 }
119 }
120
121 protected abstract CoverageParser createCoverageParser(File coverageFile, SourceLoader sourceLoader);
122
123 protected abstract List<String> getCoverageResources();
124
125 protected abstract String[][] getCoverageFixture();
126
127 private Set<Integer> toIntegerSet(final String commaSeparated) {
128 if (commaSeparated.isEmpty()) {
129 return Collections.emptySet();
130 }
131 String[] split = commaSeparated.split(",", -1);
132 Set<Integer> values = new HashSet<>();
133 for (String value : split) {
134 values.add(Integer.valueOf(value));
135 }
136 return values;
137 }
138
139 private static class SourceCollector implements SourceCallback {
140
141 private List<Source> sources = new ArrayList<>();
142
143 @Override
144 public void onBegin() {
145
146 }
147
148 @Override
149 public void onSource(Source source) {
150 sources.add(source);
151 }
152
153 @Override
154 public void onComplete() {
155
156 }
157 }
158
159 private static class ClassifierRemover extends ChainingSourceCallback {
160
161 public ClassifierRemover(SourceCallback chained) {
162 super(chained);
163 }
164
165 @Override
166 protected void onSourceInternal(Source source) {
167 source.setClassifier(null);
168 }
169 }
170
171 private static void assertCoverage(final Collection<Source> sources, final String name, final int lines,
172 final Set<Integer> coveredLines, final Set<Integer> missedLines,
173 final Set<Integer> coveredBranches, final Set<Integer> missedBranches) {
174
175 Source tested = null;
176 for (Source source : sources) {
177 if (source.getName().endsWith(name)) {
178 tested = source;
179 break;
180 }
181 }
182 if (tested == null) {
183 fail("Expected source " + name + " not found from coverage report");
184 }
185 if (tested.getCoverage().length != lines) {
186 fail("Expected " + lines + " lines for " + name + " was " + tested.getCoverage().length);
187 }
188 for (int i = 0; i < tested.getCoverage().length; i++) {
189 Integer lineNumber = i + 1;
190 String message = name + " line " + lineNumber + " coverage";
191 if (coveredLines.contains(lineNumber)) {
192 assertTrue(tested.getCoverage()[i] > 0, message);
193 } else if (missedLines.contains(lineNumber)) {
194 assertTrue(tested.getCoverage()[i] == 0, message);
195 } else {
196 assertNull(tested.getCoverage()[i], message);
197 }
198 }
199 for (final Branch b : tested.getBranchesList()) {
200 final String message = name + " branch " + b.getBranchNumber() + " coverage in line " + b.getLineNumber();
201 if (b.getHits() > 0) {
202 assertTrue(coveredBranches.contains(b.getLineNumber()), message);
203 } else {
204 assertTrue(missedBranches.contains(b.getLineNumber()), message);
205 }
206 }
207 }
208 }