1
2
3
4
5 package mockit.coverage.lines;
6
7 import static java.util.Collections.emptyList;
8
9 import edu.umd.cs.findbugs.annotations.NonNull;
10 import edu.umd.cs.findbugs.annotations.Nullable;
11
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15
16 import mockit.asm.controlFlow.Label;
17 import mockit.coverage.CallPoint;
18
19 import org.checkerframework.checker.index.qual.NonNegative;
20
21
22
23
24 public final class LineCoverageData extends LineSegmentData {
25 private static final long serialVersionUID = -6233980722802474992L;
26
27
28 @NonNull
29 private List<BranchCoverageData> branches;
30 @NonNegative
31 private transient int segments;
32
33 LineCoverageData() {
34 branches = emptyList();
35 }
36
37 @NonNegative
38 public int addBranchingPoint(@NonNull Label jumpSource, @NonNull Label jumpTarget) {
39 int initialIndex = branches.size();
40
41 if (initialIndex == 0) {
42 branches = new ArrayList<>(4);
43 }
44
45 branches.add(new BranchCoverageData(jumpSource));
46 branches.add(new BranchCoverageData(jumpTarget));
47 return initialIndex;
48 }
49
50 void markLastSegmentAsEmpty() {
51 BranchCoverageData lastBranch = branches.get(branches.size() - 1);
52 lastBranch.markAsEmpty();
53 }
54
55 private boolean noBranchesYet() {
56 return branches == Collections.<BranchCoverageData> emptyList();
57 }
58
59 @NonNull
60 public BranchCoverageData getBranchData(@NonNegative int index) {
61 return branches.get(index);
62 }
63
64 boolean acceptsAdditionalCallPoints(@NonNegative int branchIndex) {
65 BranchCoverageData data = branches.get(branchIndex);
66 return data.acceptsAdditionalCallPoints();
67 }
68
69 @NonNegative
70 int registerExecution(@NonNegative int branchIndex, @Nullable CallPoint callPoint) {
71 BranchCoverageData data = branches.get(branchIndex);
72 return data.registerExecution(callPoint);
73 }
74
75 public boolean containsBranches() {
76 return !noBranchesYet();
77 }
78
79 @NonNull
80 public List<BranchCoverageData> getBranches() {
81 return branches;
82 }
83
84 boolean isValidBranch(@NonNegative int branchIndex) {
85 return branches.get(branchIndex) != BranchCoverageData.INVALID;
86 }
87
88 @NonNegative
89 public int getNumberOfSegments() {
90 int previouslyCounted = segments;
91
92 if (previouslyCounted > 0) {
93 return previouslyCounted;
94 }
95
96 int n = branches.size();
97 int count = 1;
98
99 for (int targetBranchIndex = 1; targetBranchIndex < n; targetBranchIndex += 2) {
100 BranchCoverageData targetBranch = branches.get(targetBranchIndex);
101 int targetLine = targetBranch.getLine();
102
103 if (targetLine > 0) {
104 BranchCoverageData sourceBranch = branches.get(targetBranchIndex - 1);
105 int sourceLine = sourceBranch.getLine();
106
107 if (targetLine == sourceLine) {
108 count++;
109 }
110
111 if (!targetBranch.isEmpty()) {
112 count++;
113 }
114 }
115 }
116
117 segments = count;
118 return count;
119 }
120
121 @NonNegative
122 public int getNumberOfCoveredSegments() {
123 int segmentsCovered = isCovered() ? 1 : 0;
124 int n = branches.size();
125
126 if (n == 0) {
127 return segmentsCovered;
128 }
129
130 for (int sourceBranchIndex = 0; sourceBranchIndex < n; sourceBranchIndex += 2) {
131 BranchCoverageData sourceBranch = branches.get(sourceBranchIndex);
132 BranchCoverageData targetBranch = branches.get(sourceBranchIndex + 1);
133
134 if (sourceBranch.isCovered() && !targetBranch.isEmpty()) {
135 segmentsCovered++;
136 }
137
138 if (targetBranch.isCovered()) {
139 int targetLine = targetBranch.getLine();
140
141 if (targetLine == sourceBranch.getLine()) {
142 segmentsCovered++;
143 }
144 }
145 }
146
147 return segmentsCovered;
148 }
149
150 @NonNegative
151 public int getNumberOfBranchingSourcesAndTargets() {
152 int n = branches.size();
153
154 if (n == 0) {
155 return 0;
156 }
157
158 int count = 0;
159
160 for (int sourceBranchIndex = 0; sourceBranchIndex < n; sourceBranchIndex += 2) {
161 BranchCoverageData sourceBranch = branches.get(sourceBranchIndex);
162
163 if (!sourceBranch.isEmpty()) {
164 count++;
165 }
166
167 count++;
168 }
169
170 return count;
171 }
172
173 @NonNegative
174 public int getNumberOfCoveredBranchingSourcesAndTargets() {
175 int n = branches.size();
176
177 if (n == 0) {
178 return 0;
179 }
180
181 int sourcesAndTargetsCovered = 0;
182
183 for (int sourceBranchIndex = 0; sourceBranchIndex < n; sourceBranchIndex += 2) {
184 BranchCoverageData sourceBranch = branches.get(sourceBranchIndex);
185 BranchCoverageData targetBranch = branches.get(sourceBranchIndex + 1);
186
187 if (sourceBranch.isCovered()) {
188 sourcesAndTargetsCovered++;
189 }
190
191 if (targetBranch.isCovered()) {
192 int targetLine = targetBranch.getLine();
193
194 if (targetLine == sourceBranch.getLine()) {
195 sourcesAndTargetsCovered++;
196 }
197 }
198 }
199
200 return sourcesAndTargetsCovered;
201 }
202
203 void addCountsFromPreviousTestRun(@NonNull LineCoverageData previousData) {
204 addExecutionCountAndCallPointsFromPreviousTestRun(previousData);
205
206 if (containsBranches()) {
207 for (int i = 0, n = branches.size(); i < n; i++) {
208 BranchCoverageData segmentData = branches.get(i);
209 BranchCoverageData previousSegmentData = previousData.branches.get(i);
210
211 segmentData.addExecutionCountAndCallPointsFromPreviousTestRun(previousSegmentData);
212 }
213 }
214 }
215 }