SpoonLabs / npefix

Open-science code of the program repair tool described in "Dynamic Patch Generation for Null Pointer Exceptions Using Metaprogramming" (SANER'17)
https://hal.archives-ouvertes.fr/hal-01419861/document
14 stars 9 forks source link

NPEFix on Closure throws a "spoon.SpoonException: Cannot create MethodTypingContext" #20

Open jose opened 4 years ago

jose commented 4 years ago

Dear NPEFix's maintainers,

I've been trying to run NPEFix on Closure from the Defects4J benchmark but no success so far. I'm getting a "spoon.SpoonException: Cannot create MethodTypingContext" exception for every single repair attempt.

Please find below a step-by-step to reproduce the exception.

$ java -version
java version "1.8.0_212"
Java(TM) SE Runtime Environment (build 1.8.0_212-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)

$ mkdir "/tmp/npefix-on-d4j-closure"

Get NPEfix

$ cd "/tmp/npefix-on-d4j-closure"
$ git clone git@github.com:SpoonLabs/npefix.git # commit 80cfc38d4c3d5244c1a74c86e285193bb2670ea6
$ cd npefix
$ mvn install
$ export NPEFIX_JAR="/tmp/npefix-on-d4j-closure/npefix/target/npefix-0.8-SNAPSHOT-jar-with-dependencies.jar"

Get Defects4J

$ cd "/tmp/npefix-on-d4j-closure"
$ git clone git@github.com:rjust/defects4j.git # commit 3ec3d9242b922578d8cd6a045b5fa2a3c27bbdc9
$ cd defects4j
$ ./init.sh
$ export D4J_HOME="/private/tmp/npefix-on-d4j-closure/defects4j"

Checkout and compile Closure-1b

$ cd "/tmp/npefix-on-d4j-closure"
$ "$D4J_HOME/framework/bin/defects4j" checkout -p "Closure" -v "1b" -w "Closure-1b"
$ cd "Closure-1b"
$ "$D4J_HOME/framework/bin/defects4j" compile

Repair Closure-1b

$ cd "/tmp/npefix-on-d4j-closure/Closure-1b"
$ src_dir=$("$D4J_HOME/framework/bin/defects4j" export -p dir.src.classes)
$ test_dir=$("$D4J_HOME/framework/bin/defects4j" export -p dir.src.tests)
$ classpath=$("$D4J_HOME/framework/bin/defects4j" export -p cp.test)
$ java -jar "$NPEFIX_JAR" \
    --test "com.google.javascript.jscomp.CommandLineRunnerTest:com.google.javascript.jscomp.CompilerTest:com.google.javascript.jscomp.IntegrationTest:com.google.javascript.jscomp.OptimizeCallsTest:com.google.javascript.jscomp.RemoveUnusedVarsTest:com.google.javascript.jscomp.jsonml.SecureCompilerTest" \
    --iteration 100 \
    --complianceLevel 8 \
    --workingdirectory . \
    --source "$src_dir:$test_dir" \
    --classpath "$classpath" \
    --repairStrategy "fr.inria.spirals.npefix.main.all.DefaultRepairStrategy"

TernarySplitter  in 207ms
return (mismatchA == null) && (mismatchB == null)
return (mismatchA == null) && (mismatchB == null)
return (key != null) && (key.length() > 0)
Preconditions.checkState(references != null)
Preconditions.checkState(key != null)
Preconditions.checkState(id != null)
...
return registerCall != null
Preconditions.checkState(nameNode != null)
Preconditions.checkState(value != null)
Preconditions.checkState(value != null)
Preconditions.checkArgument(paths != null)
return properties.get(propertyName) != null
return getSlot(propertyName) != null
return properties.remove(name) != null
CheckNotNull  in 3321ms

Usage: java -jar npefix.jar
                          (-s|--source) source1:source2:...:sourceN  (-c|--classpath) <classpath> (-t|--test) test1:test2:...:testN  [--complianceLevel <complianceLevel>] [(-i|--iteration) <iteration>] [(-w|--workingdirectory) <workingdirectory>] [--repairStrategy <repairStrategy>]

  (-s|--source) source1:source2:...:sourceN
        Define the path to the source code of the project.

  (-c|--classpath) <classpath>
        Define the classpath of the project.

  (-t|--test) test1:test2:...:testN
        Define the tests of the project (both failing and passing),
        fully-qualified, separated with ':' (even if the classpath contains
        other tests, only those are considered.

  [--complianceLevel <complianceLevel>]
        The compliance level of the project. (default: 7)

  [(-i|--iteration) <iteration>]
        The maximum number of npefix iteration. (default: 100)

  [(-w|--workingdirectory) <workingdirectory>]
        Define the location where npefix will put its files. (default: .)

  [--repairStrategy <repairStrategy>]
        Define the repair strategy used by NPEFix. (default:
        fr.inria.spirals.npefix.main.all.DefaultRepairStrategy)

Exception in thread "main" spoon.SpoonException: Cannot create MethodTypingContext for method declared in different ClassTypingContext
    at spoon.support.visitor.MethodTypingContext.setMethod(MethodTypingContext.java:63)
    at spoon.support.visitor.ClassTypingContext.isSameSignature(ClassTypingContext.java:628)
    at spoon.support.visitor.ClassTypingContext.isSameSignature(ClassTypingContext.java:303)
    at spoon.support.reflect.declaration.CtTypeImpl$2.accept(CtTypeImpl.java:915)
    at spoon.support.reflect.declaration.CtTypeImpl$2.accept(CtTypeImpl.java:911)
    at spoon.reflect.visitor.chain.CtQueryImpl$OutputFunctionWrapper._accept(CtQueryImpl.java:459)
    at spoon.reflect.visitor.chain.CtQueryImpl$AbstractStep.accept(CtQueryImpl.java:307)
    at spoon.reflect.visitor.filter.AllTypeMembersFunction$1.accept(AllTypeMembersFunction.java:96)
    at spoon.reflect.visitor.filter.AllTypeMembersFunction$1.accept(AllTypeMembersFunction.java:79)
    at spoon.reflect.visitor.chain.CtQueryImpl$OutputFunctionWrapper._accept(CtQueryImpl.java:459)
    at spoon.reflect.visitor.chain.CtQueryImpl$AbstractStep.accept(CtQueryImpl.java:307)
    at spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction.sendResult(SuperInheritanceHierarchyFunction.java:360)
    at spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction.sendResultWithListener(SuperInheritanceHierarchyFunction.java:312)
    at spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction.visitSuperInterfaces(SuperInheritanceHierarchyFunction.java:299)
    at spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction.visitSuperClasses(SuperInheritanceHierarchyFunction.java:268)
    at spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction.lambda$visitSuperClasses$1(SuperInheritanceHierarchyFunction.java:280)
    at spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction.sendResultWithListener(SuperInheritanceHierarchyFunction.java:314)
    at spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction.visitSuperClasses(SuperInheritanceHierarchyFunction.java:279)
    at spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction.apply(SuperInheritanceHierarchyFunction.java:250)
    at spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction.apply(SuperInheritanceHierarchyFunction.java:36)
    at spoon.reflect.visitor.chain.CtQueryImpl$LazyFunctionWrapper._accept(CtQueryImpl.java:492)
    at spoon.reflect.visitor.chain.CtQueryImpl$AbstractStep.accept(CtQueryImpl.java:307)
    at spoon.reflect.visitor.chain.CtQueryImpl.forEach(CtQueryImpl.java:93)
  ...
  ...
    at spoon.support.visitor.ProcessingVisitor.scan(ProcessingVisitor.java:66)
    at spoon.support.QueueProcessingManager.process(QueueProcessingManager.java:118)
    at fr.inria.spirals.npefix.main.all.Launcher.instrument(Launcher.java:105)
    at fr.inria.spirals.npefix.main.run.Main.run(Main.java:70)
    at fr.inria.spirals.npefix.main.run.Main.main(Main.java:50)

Is this a known issue or am I running NPEFix incorrectly?

-- Best Jose

jose commented 4 years ago

It seems that if I update spoon-core to version 8.1.0 the spoon.SpoonException: Cannot create MethodTypingContext exception is not thrown. However, another exception is thrown and make NPEFix to crash. :-/

java -jar "$NPEFIX_JAR" \
    --test "com.google.javascript.jscomp.CommandLineRunnerTest:com.google.javascript.jscomp.CompilerTest:com.google.javascript.jscomp.IntegrationTest:com.google.javascript.jscomp.OptimizeCallsTest:com.google.javascript.jscomp.RemoveUnusedVarsTest:com.google.javascript.jscomp.jsonml.SecureCompilerTest" \
    --iteration 100 \
    --complianceLevel 8 \
    --workingdirectory . \
    --source "$src_dir:$test_dir" \
    --classpath "$classpath" \
    --repairStrategy "fr.inria.spirals.npefix.main.all.DefaultRepairStrategy"

[main] INFO spoon.Launcher - Running in NOCLASSPATH mode (doc: http://spoon.gforge.inria.fr/launcher.html).
TernarySplitter  in 440ms
return (mismatchA == null) && (mismatchB == null)
return (mismatchA == null) && (mismatchB == null)
return (key != null) && (key.length() > 0)
Preconditions.checkState(references != null)
Preconditions.checkState(key != null)
Preconditions.checkState(id != null)
...
Preconditions.checkState((currentTracer != null) && (currentPassName != null))
Preconditions.checkState((currentTracer != null) && (currentPassName != null))
Preconditions.checkState(injectableBlock != null)
CheckNotNull  in 2740ms
ForceNullInit in 183ms
AddImplicitCastChecker --> 15 in 557ms
BeforeDeref --> 20352 (failed:0) in 4607ms
target--> 23537 (failed:0) in 39152ms
TryRegister # Try: 95 in 384ms
Assign --> 9678 (failed: 0) in 18111ms
VarInit --> 3030 in 4123ms
MethodEncapsulation # Method: 7470 in 64593ms
ConstructorEncapsulation # Constructor: 771 in 22042ms
VariableFor in 1210ms
spoon.support.compiler.SnippetCompilationError: The import com.google.debugging.sourcemap.proto.Mapping.OriginalMapping.Builder collides with another import statement at SourceMapConsumerV1.java:11
    at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.reportProblemsWhenCompiling(JDTBasedSpoonCompiler.java:609)
    at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.compile(JDTBasedSpoonCompiler.java:167)
    at fr.inria.spirals.npefix.main.all.Launcher.instrument(Launcher.java:109)
    at fr.inria.spirals.npefix.main.run.Main.run(Main.java:70)
    at fr.inria.spirals.npefix.main.run.Main.main(Main.java:50)

Usage: java -jar npefix.jar
                          (-s|--source) source1:source2:...:sourceN  (-c|--classpath) <classpath> (-t|--test) test1:test2:...:testN  [--complianceLevel <complianceLevel>] [(-i|--iteration) <iteration>] [(-w|--workingdirectory) <workingdirectory>] [--repairStrategy <repairStrategy>]

  (-s|--source) source1:source2:...:sourceN
        Define the path to the source code of the project.

  (-c|--classpath) <classpath>
        Define the classpath of the project.

  (-t|--test) test1:test2:...:testN
        Define the tests of the project (both failing and passing),
        fully-qualified, separated with ':' (even if the classpath contains
        other tests, only those are considered.

  [--complianceLevel <complianceLevel>]
        The compliance level of the project. (default: 7)

  [(-i|--iteration) <iteration>]
        The maximum number of npefix iteration. (default: 100)

  [(-w|--workingdirectory) <workingdirectory>]
        Define the location where npefix will put its files. (default: .)

  [--repairStrategy <repairStrategy>]
        Define the repair strategy used by NPEFix. (default:
        fr.inria.spirals.npefix.main.all.DefaultRepairStrategy)

Exception in thread "main" spoon.support.compiler.SnippetCompilationError: The import com.google.debugging.sourcemap.proto.Mapping.OriginalMapping.Builder collides with another import statement at SourceMapConsumerV1.java:11
    at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.reportProblemsWhenCompiling(JDTBasedSpoonCompiler.java:609)
    at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.compile(JDTBasedSpoonCompiler.java:167)
    at fr.inria.spirals.npefix.main.all.Launcher.instrument(Launcher.java:109)
    at fr.inria.spirals.npefix.main.run.Main.run(Main.java:70)
    at fr.inria.spirals.npefix.main.run.Main.main(Main.java:50)
tdurieux commented 4 years ago

It is probably a case that we don't handle properly in NPEFix, we will need to debug and fix NPEFix to handle this case (if possible). NPEFix does a LOT of code instrumentation and it is difficult to be 100% compatible with all existing java projects.

jose commented 4 years ago

Thanks @tdurieux. Looking forward for that fix.