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