View Javadoc
1   package integrationTests;
2   
3   import static java.lang.reflect.Modifier.isAbstract;
4   import static java.lang.reflect.Modifier.isFinal;
5   
6   import static org.junit.jupiter.api.Assertions.assertEquals;
7   import static org.junit.jupiter.api.Assertions.assertFalse;
8   import static org.junit.jupiter.api.Assertions.assertNotNull;
9   import static org.junit.jupiter.api.Assertions.assertTrue;
10  
11  import edu.umd.cs.findbugs.annotations.NonNull;
12  import edu.umd.cs.findbugs.annotations.Nullable;
13  
14  import java.lang.reflect.Field;
15  import java.util.List;
16  import java.util.Map;
17  
18  import mockit.coverage.CallPoint;
19  import mockit.coverage.data.CoverageData;
20  import mockit.coverage.data.FileCoverageData;
21  import mockit.coverage.dataItems.InstanceFieldData;
22  import mockit.coverage.dataItems.PerFileDataCoverage;
23  import mockit.coverage.dataItems.StaticFieldData;
24  import mockit.coverage.lines.BranchCoverageData;
25  import mockit.coverage.lines.LineCoverageData;
26  import mockit.coverage.lines.PerFileLineCoverage;
27  
28  import org.checkerframework.checker.index.qual.NonNegative;
29  import org.junit.jupiter.api.BeforeEach;
30  
31  @SuppressWarnings("JUnitTestCaseWithNoTests")
32  public class CoverageTest {
33      @Nullable
34      protected static FileCoverageData fileData;
35      @Nullable
36      private static String testedClassSimpleName;
37  
38      @BeforeEach
39      public final void findCoverageData() throws Exception {
40          Field testedField = getClass().getDeclaredField("tested");
41          Class<?> testedClass = testedField.getType();
42  
43          if (testedClass != Object.class) {
44              findFileDate(testedClass);
45              setTestedFieldToNewInstanceIfApplicable(testedField);
46          }
47      }
48  
49      private void findFileDate(@NonNull Class<?> testedClass) {
50          testedClassSimpleName = testedClass.getSimpleName();
51  
52          String classFilePath = testedClass.getName().replace('.', '/') + ".java";
53          Map<String, FileCoverageData> data = CoverageData.instance().getFileToFileData();
54          fileData = data.get(classFilePath);
55  
56          assertNotNull(fileData, "FileCoverageData not found for " + classFilePath);
57      }
58  
59      private void setTestedFieldToNewInstanceIfApplicable(@NonNull Field testedField) throws Exception {
60          Class<?> testedClass = testedField.getType();
61  
62          if (!testedClass.isEnum() && !isAbstract(testedClass.getModifiers()) && !isFinal(testedField.getModifiers())) {
63              testedField.setAccessible(true);
64  
65              if (testedField.get(this) == null) {
66                  // noinspection ClassNewInstance
67                  Object newTestedInstance = testedClass.getDeclaredConstructor().newInstance();
68  
69                  testedField.set(this, newTestedInstance);
70              }
71          }
72      }
73  
74      @NonNull
75      private FileCoverageData fileData() {
76          if (fileData == null) {
77              Object testedInstance;
78  
79              try {
80                  Field testedField = getClass().getDeclaredField("tested");
81                  testedInstance = testedField.get(this);
82              } catch (NoSuchFieldException | IllegalAccessException e) {
83                  throw new RuntimeException(e);
84              }
85  
86              Class<?> testedClass = testedInstance.getClass();
87              findFileDate(testedClass);
88          }
89  
90          return fileData;
91      }
92  
93      // Line Coverage assertions
94      // ////////////////////////////////////////////////////////////////////////////////////////////////////////////
95  
96      protected final void assertLines(@NonNegative int startingLine, @NonNegative int endingLine,
97              @NonNegative int expectedLinesExecuted) {
98          PerFileLineCoverage lineCoverageInfo = fileData().lineCoverageInfo;
99          int lineCount = lineCoverageInfo.getLineCount();
100         assertTrue(lineCount >= startingLine, "Starting line not found");
101         assertTrue(lineCount >= endingLine, "Ending line not found");
102 
103         int linesExecuted = 0;
104 
105         for (int line = startingLine; line <= endingLine; line++) {
106             if (lineCoverageInfo.getExecutionCount(line) > 0) {
107                 linesExecuted++;
108             }
109         }
110 
111         assertEquals(expectedLinesExecuted, linesExecuted, "Unexpected number of lines executed:");
112     }
113 
114     protected final void assertLine(@NonNegative int line, @NonNegative int expectedSegments,
115             @NonNegative int expectedCoveredSegments, int... expectedExecutionCounts) {
116         PerFileLineCoverage info = fileData().lineCoverageInfo;
117         LineCoverageData lineData = info.getLineData(line);
118 
119         assertEquals(expectedSegments, info.getNumberOfSegments(line), "Segments:");
120         assertEquals(expectedCoveredSegments, lineData.getNumberOfCoveredSegments(), "Covered segments:");
121         assertEquals(expectedExecutionCounts[0], info.getExecutionCount(line), "Execution count:");
122 
123         for (int i = 1; i < expectedExecutionCounts.length; i++) {
124             BranchCoverageData segmentData = lineData.getBranchData(i - 1);
125 
126             int executionCount = segmentData.getExecutionCount();
127             assertEquals(expectedExecutionCounts[i], executionCount,
128                     "Execution count for line " + line + ", segment " + i + ':');
129 
130             List<CallPoint> callPoints = segmentData.getCallPoints();
131 
132             if (callPoints != null) {
133                 int callPointCount = 0;
134 
135                 for (CallPoint callPoint : callPoints) {
136                     callPointCount++;
137                     callPointCount += callPoint.getRepetitionCount();
138                 }
139 
140                 assertEquals(executionCount, callPointCount, "Missing call points for line " + line + ", segment " + i);
141             }
142         }
143     }
144 
145     protected final void assertBranchingPoints(@NonNegative int line, @NonNegative int expectedSourcesAndTargets,
146             @NonNegative int expectedCoveredSourcesAndTargets) {
147         PerFileLineCoverage lineCoverageInfo = fileData().lineCoverageInfo;
148         LineCoverageData lineData = lineCoverageInfo.getLineData(line);
149 
150         int sourcesAndTargets = lineCoverageInfo.getNumberOfBranchingSourcesAndTargets(line);
151         assertEquals(expectedSourcesAndTargets, sourcesAndTargets, "Sources and targets:");
152 
153         int coveredSourcesAndTargets = lineData.getNumberOfCoveredBranchingSourcesAndTargets();
154         assertEquals(expectedCoveredSourcesAndTargets, coveredSourcesAndTargets, "Covered sources and targets:");
155     }
156 
157     // Data Coverage assertions
158     // ////////////////////////////////////////////////////////////////////////////////////////////////////////////
159 
160     protected final void assertFieldIgnored(@NonNull String fieldName) {
161         String fieldId = testedClassSimpleName + '.' + fieldName;
162         PerFileDataCoverage info = fileData().dataCoverageInfo;
163         assertFalse(info.staticFieldsData.containsKey(fieldId),
164                 "Field " + fieldName + " should not have static coverage data");
165         assertFalse(info.instanceFieldsData.containsKey(fieldId),
166                 "Field " + fieldName + " should not have instance coverage data");
167     }
168 
169     protected static void assertStaticFieldCovered(@NonNull String fieldName) {
170         assertTrue(isStaticFieldCovered(fieldName), "Static field " + fieldName + " should be covered");
171     }
172 
173     private static boolean isStaticFieldCovered(@NonNull String fieldName) {
174         String classAndFieldNames = testedClassSimpleName + '.' + fieldName;
175         StaticFieldData staticFieldData = fileData.dataCoverageInfo.staticFieldsData.get(classAndFieldNames);
176 
177         return staticFieldData.isCovered();
178     }
179 
180     protected static void assertStaticFieldUncovered(@NonNull String fieldName) {
181         assertFalse(isStaticFieldCovered(fieldName), "Static field " + fieldName + " should not be covered");
182     }
183 
184     protected static void assertInstanceFieldCovered(@NonNull String fieldName) {
185         assertTrue(isInstanceFieldCovered(fieldName), "Instance field " + fieldName + " should be covered");
186     }
187 
188     private static boolean isInstanceFieldCovered(@NonNull String fieldName) {
189         return getInstanceFieldData(fieldName).isCovered();
190     }
191 
192     private static InstanceFieldData getInstanceFieldData(@NonNull String fieldName) {
193         String classAndFieldNames = testedClassSimpleName + '.' + fieldName;
194         return fileData.dataCoverageInfo.instanceFieldsData.get(classAndFieldNames);
195     }
196 
197     protected static void assertInstanceFieldUncovered(@NonNull String fieldName) {
198         assertFalse(isInstanceFieldCovered(fieldName), "Instance field " + fieldName + " should not be covered");
199     }
200 
201     protected static void assertInstanceFieldUncovered(@NonNull String fieldName,
202             @NonNull Object... uncoveredInstances) {
203         String msg = "Instance field " + fieldName + " should not be covered";
204         InstanceFieldData fieldData = getInstanceFieldData(fieldName);
205         List<Integer> ownerInstances = fieldData.getOwnerInstancesWithUnreadAssignments();
206 
207         assertEquals(uncoveredInstances.length, ownerInstances.size(), msg);
208 
209         for (Object uncoveredInstance : uncoveredInstances) {
210             Integer instanceId = System.identityHashCode(uncoveredInstance);
211             assertTrue(ownerInstances.contains(instanceId), msg);
212         }
213     }
214 
215     protected static void verifyDataCoverage(@NonNegative int expectedItems, @NonNegative int expectedCoveredItems,
216             @NonNegative int expectedCoverage) {
217         PerFileDataCoverage info = fileData.dataCoverageInfo;
218         assertEquals(expectedItems, info.getTotalItems(), "Total data items:");
219         assertEquals(expectedCoveredItems, info.getCoveredItems(), "Covered data items:");
220         assertEquals(expectedCoverage, info.getCoveragePercentage(), "Data coverage:");
221     }
222 }