@@ -17,14 +17,15 @@ most of generated branches would be `NPE` branches, while useful paths could be
1717
1818Beyond that, in many cases the ` null ` value of a field can't be generated using the public API
1919of the class. This is particularly true for final fields, especially in system classes.
20- Automatically generated tests assign ` null ` values to fields in questions using reflection,
20+ it is also often true for non-public fields from standard library and third-party libraries (even setters often do not
21+ allow ` null ` values). Automatically generated tests assign ` null ` values to fields in questions using reflection,
2122but these tests may be uninformative as the corresponding ` NPE ` branches would never occur
2223in the real code that limits itself to the public API.
2324
2425## The solution
2526
2627To discard irrelevant ` NPE ` branches, we can speculatively mark fields we as non-nullable even they
27- do not have an explicit ` @NotNull ` annotation. In particular, we can use this approach to final
28+ do not have an explicit ` @NotNull ` annotation. In particular, we can use this approach to final and non-public
2829fields of system classes, as they are usually correctly initialized and are not equal ` null ` .
2930
3031At the same time, we can't always add the "not null" hard constraint for the field: it would break
@@ -38,18 +39,18 @@ no way to check whether the address corresponds to a final field, as the corresp
3839of the global graph would refer to a local variable. The only place where we have the complete
3940information about the field is this method.
4041
41- We use the following approach. If the field is final and belongs to a system class,
42- we mark it as a speculatively non-nullable in the memory
42+ We use the following approach. If the field belongs to a library class (according to ` soot.SootClass.isLibraryClass ` )
43+ and is final or non-public, we mark it as a speculatively non-nullable in the memory
4344(see ` org.utbot.engine.Memory.speculativelyNotNullAddresses ` ). During the NPE check
4445we will add the ` !isSpeculativelyNotNull(addr(field)) ` constraint
4546to the ` NPE ` branch together with the usual ` addr(field) == null ` constraint.
4647
47- For final fields, these two conditions can't be satisfied at the same time, as we speculatively
48- mark final fields as non-nullable. As a result, the NPE branch would be discarded. If a field
49- is not final, the condition is satisfiable, so the NPE branch would stay alive.
48+ For final/non-public fields, these two conditions can't be satisfied at the same time, as we speculatively
49+ mark such fields as non-nullable. As a result, the NPE branch would be discarded. If a field
50+ is public or not final, the condition is satisfiable, so the NPE branch would stay alive.
5051
51- We limit this approach to the system classes only, because it is hard to speculatively assume
52- something about non-nullability of final fields in the user code.
52+ We limit this approach to the library classes only, because it is hard to speculatively assume
53+ something about non-nullability of final/non-public fields in the user code.
5354
5455The same approach can be extended for other cases where we want to speculatively consider some
5556fields as non-nullable to prevent ` NPE ` branch generation.
0 commit comments