[pulse] add Java tests

Summary:
Start with tests about dynamic dispatch to test the upcoming
pre-analysis.

Reviewed By: ezgicicek

Differential Revision: D21594496

fbshipit-source-id: 1771ea968
master
Jules Villard 5 years ago committed by Facebook GitHub Bot
parent 65d2bc692d
commit bf97abfbd3

@ -165,6 +165,7 @@ DIRECT_TESTS += \
java_litho-required-props \
java_performance \
java_performance-exclusive \
java_pulse \
java_purity \
java_quandary \
java_racerd \

@ -0,0 +1,157 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package codetoanalyze.java.infer;
public class DynamicDispatch {
static interface Interface {
public Object foo();
}
static class Impl implements Interface {
@Override
public Object foo() {
return null;
}
}
static void interfaceShouldNotCauseFalseNegativeEasyBad() {
Interface i = new Impl();
// should be a warning since Impl's implementation of foo returns null
i.foo().toString();
}
static void interfaceShouldNotCauseFalseNegativeHardOK(Interface i) {
i.foo().toString();
}
static void callWithBadImplementationBad_FN(Impl impl) {
interfaceShouldNotCauseFalseNegativeHardOK(impl);
}
static class Supertype {
Object foo() {
return new Object();
}
Object bar() {
return null;
}
}
static class Subtype extends Supertype {
@Override
Object foo() {
return null;
}
@Override
Object bar() {
return new Object();
}
}
static void dynamicDispatchShouldNotCauseFalseNegativeEasyBad() {
Supertype o = new Subtype();
// should report a warning because we know the dynamic type of o is Subtype
o.foo().toString();
}
static void dynamicDispatchShouldNotCauseFalsePositiveEasyOK() {
Supertype o = new Subtype();
// should not report a warning because we know the dynamic type of o is Subtype
o.bar().toString();
}
static void dynamicDispatchShouldNotReportWhenCallingSupertypeOK(Supertype o) {
// should not report a warning because the Supertype implementation
// of foo() does not return null
o.foo().toString();
}
static void dynamicDispatchShouldReportWhenCalledWithSubtypeParameterBad_FN(Subtype o) {
// should report a warning because the Subtype implementation
// of foo() returns null
dynamicDispatchShouldNotReportWhenCallingSupertypeOK(o);
}
static Object dynamicDispatchWrapperFoo(Supertype o) {
return o.foo();
}
static Object dynamicDispatchWrapperBar(Supertype o) {
return o.bar();
}
static void dynamicDispatchCallsWrapperWithSupertypeOK() {
// Should not report because Supertype.foo() does not return null
Supertype o = new Supertype();
dynamicDispatchWrapperFoo(o).toString();
}
static void dynamicDispatchCallsWrapperWithSupertypeBad() {
// Should report because Supertype.bar() returns null
Supertype o = new Supertype();
dynamicDispatchWrapperBar(o).toString();
}
static void dynamicDispatchCallsWrapperWithSubtypeBad_FN() {
// Should report because Subtype.foo() returns null
Supertype o = new Subtype();
dynamicDispatchWrapperFoo(o).toString();
}
static void dynamicDispatchCallsWrapperWithSubtypeOK_FP() {
// Should not report because Subtype.bar() does not returns null
Supertype o = new Subtype();
dynamicDispatchWrapperBar(o).toString();
}
static class WithField {
Supertype mField;
WithField(Supertype t) {
mField = t;
}
static void dispatchOnFieldOK_FP() {
Supertype subtype = new Subtype();
WithField object = new WithField(subtype);
object.mField.bar().toString();
}
static void dispatchOnFieldBad_FN() {
Supertype subtype = new Subtype();
WithField object = new WithField(subtype);
object.mField.foo().toString();
}
}
private Object callFoo(Supertype o) {
return o.foo();
}
void dynamicResolutionWithPrivateMethodBad_FN() {
Supertype subtype = new Subtype();
callFoo(subtype).toString();
}
Object variadicMethod(Supertype... args) {
if (args.length == 0) {
return null;
} else {
return args[0].foo();
}
}
void dynamicResolutionWithVariadicMethodBad() {
Supertype subtype = new Subtype();
variadicMethod(subtype, null, null).toString();
}
}

@ -0,0 +1,12 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
TESTS_DIR = ../../..
INFER_OPTIONS = --pulse-only --debug-exceptions
INFERPRINT_OPTIONS = --issues-tests
SOURCES = $(wildcard *.java)
include $(TESTS_DIR)/javac.make

@ -0,0 +1,6 @@
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch$WithField.dispatchOnFieldOK_FP():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch$Supertype.bar()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch$Supertype.bar()`,return from call to `Object DynamicDispatch$Supertype.bar()`,assigned,invalid access occurs here]
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.dynamicDispatchCallsWrapperWithSubtypeOK_FP():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)` here,when calling `Object DynamicDispatch$Supertype.bar()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,return from call to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,assigned,invalid access occurs here]
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.dynamicDispatchCallsWrapperWithSupertypeBad():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)` here,when calling `Object DynamicDispatch$Supertype.bar()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,return from call to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,assigned,invalid access occurs here]
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.dynamicDispatchShouldNotCauseFalseNegativeEasyBad():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch$Subtype.foo()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch$Subtype.foo()`,return from call to `Object DynamicDispatch$Subtype.foo()`,assigned,invalid access occurs here]
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.dynamicResolutionWithVariadicMethodBad():void, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch.variadicMethod(DynamicDispatch$Supertype[])` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch.variadicMethod(DynamicDispatch$Supertype[])`,return from call to `Object DynamicDispatch.variadicMethod(DynamicDispatch$Supertype[])`,assigned,invalid access occurs here]
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.interfaceShouldNotCauseFalseNegativeEasyBad():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch$Impl.foo()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch$Impl.foo()`,return from call to `Object DynamicDispatch$Impl.foo()`,assigned,invalid access occurs here]
Loading…
Cancel
Save