Skip to content

Surviving pitest mutations for conditions reducing time complexity at PackageObjectFactory #11902

@Vyom-Yadav

Description

@Vyom-Yadav

Two mutation cases to discuss, these conditions are present to reduce the time complexity.

<mutation unstable="false">
<sourceFile>PackageObjectFactory.java</sourceFile>
<mutatedClass>com.puppycrawl.tools.checkstyle.PackageObjectFactory</mutatedClass>
<mutatedMethod>createModule</mutatedMethod>
<mutator>org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_IF</mutator>
<description>removed conditional - replaced equality check with true</description>
<lineContent>if (thirdPartyNameToFullModuleNames == null) {</lineContent>
</mutation>

<mutation unstable="false">                                                                          
  <sourceFile>PackageObjectFactory.java</sourceFile>                                                 
  <mutatedClass>com.puppycrawl.tools.checkstyle.PackageObjectFactory</mutatedClass>                  
  <mutatedMethod>createModule</mutatedMethod>                                                        
  <mutator>org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_IF</mutator>
  <description>removed conditional - replaced equality check with true</description>                 
  <lineContent>if (thirdPartyNameToFullModuleNames == null) {</lineContent>                          
</mutation>                                                                                          

Complete relevant code

if (instance == null) {
if (thirdPartyNameToFullModuleNames == null) {
thirdPartyNameToFullModuleNames =
generateThirdPartyNameToFullModuleName(moduleClassLoader);
}

This null check is present to reduce the time complexity, the method generateThirdPartyNameToFullModuleName(..) uses moduleClassLoader (final instance field) and packages (another final instance field) so even if thirdPartyNameToFullModuleNames is recalculated again and again the result will be the same. The only way it can change is if you access the internal fields, for eg - packages using reflections and add an element to the set. But in the current code those fields are not modified.

<mutation unstable="false">                                                                          
  <sourceFile>PackageObjectFactory.java</sourceFile>                                                 
  <mutatedClass>com.puppycrawl.tools.checkstyle.PackageObjectFactory</mutatedClass>                  
  <mutatedMethod>createModule</mutatedMethod>                                                        
  <mutator>org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_IF</mutator>
  <description>removed conditional - replaced equality check with true</description>                 
  <lineContent>if (!name.contains(PACKAGE_SEPARATOR)) {</lineContent>                                
</mutation>                                                                                          

Complete relevant code

if (!name.contains(PACKAGE_SEPARATOR)) {
instance = createFromStandardCheckSet(name);
// find the name in third party map
if (instance == null) {
if (thirdPartyNameToFullModuleNames == null) {
thirdPartyNameToFullModuleNames =
generateThirdPartyNameToFullModuleName(moduleClassLoader);
}
instance = createObjectFromMap(name, thirdPartyNameToFullModuleNames);
}
}

The mutation is replacing the condition with true, if there is some name with PACKAGE_SEPARATOR that enters this branch, then it is guaranteed that it will still remain null.
createFromStandardCheckSet(..) the standard check set does not contain any module which has PACKAGE_SEPARATOR in its short name.
generateThirdPartyNameToFullModuleName(..) implementation guarantees it that there are no short names which contain PACKAGE_SEPARATOR as it uses Class#getSimpleName() to get the short name.
This condition is only present to reduce the time complexity. But this time complexity is enormous, 4 min to 36 minutes for "mvn verify" , see #13752 (comment)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions