Summary: Convert the last remaining tests to the new direct format: java harness and crashcontext. Remove what is left of the old testing infrastructure. Reviewed By: sblackshear Differential Revision: D3886355 fbshipit-source-id: 5117868master
parent
a2ee69975a
commit
717b61192e
@ -1,10 +1,3 @@
|
||||
|
||||
[alias]
|
||||
java = //infer/tests/endtoend:java_endtoend_tests
|
||||
java_libraries = //dependencies/java:java_libraries
|
||||
|
||||
# TODO: this line exists only to support buck integration in infer/tests/build_systems/build_integration_tests.py
|
||||
infer = //infer/tests/endtoend/java/infer:infer
|
||||
|
||||
[project]
|
||||
ignore = .git, .ml, .mli
|
||||
|
@ -1,8 +0,0 @@
|
||||
export_file(
|
||||
name = 'inferconfig',
|
||||
src = '.inferconfig',
|
||||
out = '.inferconfig',
|
||||
visibility = [
|
||||
'PUBLIC'
|
||||
]
|
||||
)
|
@ -1,82 +0,0 @@
|
||||
sources = glob(['**/*.java','**/*.json'])
|
||||
|
||||
dependencies = [
|
||||
'//dependencies/java/android/support/v4:android-support-v4',
|
||||
'//infer/annotations:annotations',
|
||||
'//infer/lib/java/android:android',
|
||||
]
|
||||
|
||||
java_library(
|
||||
name = 'checkers',
|
||||
srcs = sources,
|
||||
deps = dependencies,
|
||||
visibility = [
|
||||
'PUBLIC'
|
||||
]
|
||||
)
|
||||
|
||||
out = 'infer-out'
|
||||
inferconfig_file = '$(location //infer/tests/codetoanalyze/java:inferconfig)'
|
||||
copy_inferconfig = ' '.join(['cp', inferconfig_file, '$SRCDIR'])
|
||||
clean_cmd = ' '.join(['rm', '-rf', out])
|
||||
classpath = ':'.join([('$(classpath ' + path + ')') for path in dependencies])
|
||||
|
||||
def mk_infer_cmd(tag, srcs, stacktrace):
|
||||
infer_cmd_main = ' '.join([
|
||||
'infer',
|
||||
'--no-progress-bar',
|
||||
'--absolute-paths',
|
||||
'-a', 'crashcontext',
|
||||
'--stacktrace', stacktrace,
|
||||
'--',
|
||||
'javac',
|
||||
'-cp', classpath,
|
||||
srcs])
|
||||
out_rename = ' '.join(['cp',
|
||||
out + '/crashcontext/crashcontext.json',
|
||||
'$OUT' + "." + tag])
|
||||
return ' && '.join([infer_cmd_main, out_rename])
|
||||
|
||||
infer_cmds = [
|
||||
mk_infer_cmd(
|
||||
"MinimalCrashExample",
|
||||
"MinimalCrashExample.java",
|
||||
"MinimalCrashExample.stacktrace.json"
|
||||
),
|
||||
mk_infer_cmd(
|
||||
"MultiStackFrameCrashExample",
|
||||
"MultiStackFrameCrashExample.java",
|
||||
"MultiStackFrameCrashExample.stacktrace.json"
|
||||
),
|
||||
mk_infer_cmd(
|
||||
"BranchingCallsExample",
|
||||
"BranchingCallsExample.java",
|
||||
"BranchingCallsExample.stacktrace.json"
|
||||
),
|
||||
mk_infer_cmd(
|
||||
"MethodNameClashExample",
|
||||
"MethodNameClashExample.java",
|
||||
"MethodNameClashExample.stacktrace.json"
|
||||
),
|
||||
mk_infer_cmd(
|
||||
"NativeMethodExample",
|
||||
"NativeMethodExample.java",
|
||||
"NativeMethodExample.stacktrace.json"
|
||||
)
|
||||
]
|
||||
|
||||
# Copy the last crashcontext.json because buck expects it as the output file.
|
||||
# This will only contain the results for the last run infer_cmd above.
|
||||
copy_cmd = ' '.join(['cp', out + '/crashcontext/crashcontext.json', '$OUT'])
|
||||
command = ' && '.join([clean_cmd, copy_inferconfig, ' && '.join(infer_cmds), copy_cmd])
|
||||
|
||||
genrule(
|
||||
name = 'analyze',
|
||||
srcs = sources,
|
||||
out = 'crashcontext.json',
|
||||
cmd = command,
|
||||
deps = dependencies + [':checkers'],
|
||||
visibility = [
|
||||
'PUBLIC',
|
||||
]
|
||||
)
|
@ -0,0 +1 @@
|
||||
{"stack":[{"method_name":"codetoanalyze.java.crashcontext.BranchingCallsExample.bar():void","location":{"location_type":"call_site","file":"BranchingCallsExample.java","line":24,"blame_range":[{"start_line":22,"end_line":24}]},"callees":[{"method_name":"java.lang.String.toString():java.lang.String","callees":[]}]},{"method_name":"codetoanalyze.java.crashcontext.BranchingCallsExample.foo():void","location":{"location_type":"call_site","file":"BranchingCallsExample.java","line":29,"blame_range":[{"start_line":27,"end_line":30}]},"callees":[{"method_name":"codetoanalyze.java.crashcontext.BranchingCallsExample.bar():void","location":{"location_type":"proc_start","file":"BranchingCallsExample.java","line":22,"blame_range":[{"start_line":22,"end_line":24}]},"callees":[]},{"method_name":"codetoanalyze.java.crashcontext.BranchingCallsExample.pre_bar():void","location":{"location_type":"proc_start","file":"BranchingCallsExample.java","line":14,"blame_range":[{"start_line":14,"end_line":15}]},"callees":[]}]},{"method_name":"codetoanalyze.java.crashcontext.BranchingCallsExample.main(java.lang.String[]):void","location":{"location_type":"call_site","file":"BranchingCallsExample.java","line":34,"blame_range":[{"start_line":33,"end_line":34}]},"callees":[{"method_name":"codetoanalyze.java.crashcontext.BranchingCallsExample.foo():void","location":{"location_type":"proc_start","file":"BranchingCallsExample.java","line":27,"blame_range":[{"start_line":27,"end_line":30}]},"callees":[]}]}]}
|
@ -0,0 +1,42 @@
|
||||
# Copyright (c) 2016 - present Facebook, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under the BSD style license found in the
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
include ../Makefile
|
||||
|
||||
|
||||
ANALYZER = crashcontext
|
||||
|
||||
FILES = \
|
||||
BranchingCallsExample \
|
||||
MethodNameClashExample \
|
||||
MinimalCrashExample \
|
||||
MultiStackFrameCrashExample \
|
||||
NativeMethodExample \
|
||||
|
||||
compile:
|
||||
for file in $(FILES) ; do \
|
||||
javac -cp $(CLASSPATH) $$file.java ; \
|
||||
done
|
||||
|
||||
analyze:
|
||||
for file in $(FILES) ; do \
|
||||
$(INFER_BIN) -a $(ANALYZER) --stacktrace $$file.stacktrace.json -- javac -cp $(CLASSPATH) $$file.java >/dev/null 2>/dev/null ; \
|
||||
cp infer-out/crashcontext/crashcontext.json $$file.exp.test ; \
|
||||
done
|
||||
|
||||
# overwrite
|
||||
print:
|
||||
|
||||
# overwrite
|
||||
test: analyze
|
||||
set -e; \
|
||||
for file in $(FILES) ; do \
|
||||
diff -u $$file.exp $$file.exp.test ; \
|
||||
rm $$file.exp.test ; \
|
||||
done
|
||||
make clean
|
||||
|
@ -0,0 +1 @@
|
||||
{"stack":[{"method_name":"codetoanalyze.java.crashcontext.MethodNameClashExample$A.foo():void","location":{"location_type":"call_site","file":"MethodNameClashExample.java","line":18,"blame_range":[{"start_line":16,"end_line":18}]},"callees":[{"method_name":"java.lang.String.toString():java.lang.String","callees":[]}]},{"method_name":"codetoanalyze.java.crashcontext.MethodNameClashExample$B.foo():void","location":{"location_type":"call_site","file":"MethodNameClashExample.java","line":26,"blame_range":[{"start_line":26,"end_line":26}]},"callees":[{"method_name":"codetoanalyze.java.crashcontext.MethodNameClashExample$A.foo():void","location":{"location_type":"proc_start","file":"MethodNameClashExample.java","line":16,"blame_range":[{"start_line":16,"end_line":18}]},"callees":[]}]},{"method_name":"codetoanalyze.java.crashcontext.MethodNameClashExample.main(java.lang.String[]):void","location":{"location_type":"call_site","file":"MethodNameClashExample.java","line":32,"blame_range":[{"start_line":31,"end_line":32}]},"callees":[{"method_name":"codetoanalyze.java.crashcontext.MethodNameClashExample$B.foo():void","location":{"location_type":"proc_start","file":"MethodNameClashExample.java","line":26,"blame_range":[{"start_line":26,"end_line":26}]},"callees":[]}]}]}
|
@ -0,0 +1 @@
|
||||
{"stack":[{"method_name":"codetoanalyze.java.crashcontext.MinimalCrashExample.main(java.lang.String[]):void","location":{"location_type":"call_site","file":"MinimalCrashExample.java","line":16,"blame_range":[{"start_line":14,"end_line":16}]},"callees":[{"method_name":"java.lang.String.toString():java.lang.String","callees":[]}]}]}
|
@ -0,0 +1 @@
|
||||
{"stack":[{"method_name":"codetoanalyze.java.crashcontext.MultiStackFrameCrashExample.bar():void","location":{"location_type":"call_site","file":"MultiStackFrameCrashExample.java","line":16,"blame_range":[{"start_line":14,"end_line":16}]},"callees":[{"method_name":"java.lang.String.toString():java.lang.String","callees":[]}]},{"method_name":"codetoanalyze.java.crashcontext.MultiStackFrameCrashExample.foo():void","location":{"location_type":"call_site","file":"MultiStackFrameCrashExample.java","line":20,"blame_range":[{"start_line":19,"end_line":20}]},"callees":[{"method_name":"codetoanalyze.java.crashcontext.MultiStackFrameCrashExample.bar():void","location":{"location_type":"proc_start","file":"MultiStackFrameCrashExample.java","line":14,"blame_range":[{"start_line":14,"end_line":16}]},"callees":[]}]},{"method_name":"codetoanalyze.java.crashcontext.MultiStackFrameCrashExample.main(java.lang.String[]):void","location":{"location_type":"call_site","file":"MultiStackFrameCrashExample.java","line":24,"blame_range":[{"start_line":23,"end_line":24}]},"callees":[{"method_name":"codetoanalyze.java.crashcontext.MultiStackFrameCrashExample.foo():void","location":{"location_type":"proc_start","file":"MultiStackFrameCrashExample.java","line":19,"blame_range":[{"start_line":19,"end_line":20}]},"callees":[]}]}]}
|
@ -0,0 +1 @@
|
||||
{"stack":[{"method_name":"codetoanalyze.java.crashcontext.NativeMethodExample.foo():void","location":{"location_type":"call_site","file":"NativeMethodExample.java","line":18,"blame_range":[{"start_line":16,"end_line":18}]},"callees":[{"method_name":"java.lang.String.toString():java.lang.String","callees":[]}]},{"method_name":"sun.reflect.NativeMethodAccessorImpl.invoke0","location":{"location_type":"call_site","file":"Native Method","blame_range":[]},"callees":[]},{"method_name":"sun.reflect.NativeMethodAccessorImpl.invoke","location":{"location_type":"call_site","file":"NativeMethodAccessorImpl.java","line":62,"blame_range":[]},"callees":[]},{"method_name":"sun.reflect.DelegatingMethodAccessorImpl.invoke","location":{"location_type":"call_site","file":"DelegatingMethodAccessorImpl.java","line":43,"blame_range":[]},"callees":[]},{"method_name":"java.lang.reflect.Method.invoke","location":{"location_type":"call_site","file":"Method.java","line":497,"blame_range":[]},"callees":[]},{"method_name":"codetoanalyze.java.crashcontext.NativeMethodExample.main(java.lang.String[]):void","location":{"location_type":"call_site","file":"NativeMethodExample.java","line":27,"blame_range":[{"start_line":21,"end_line":29}]},"callees":[{"method_name":"java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]):java.lang.reflect.Method","callees":[]},{"method_name":"java.lang.reflect.Method.invoke(java.lang.Object,java.lang.Object[]):java.lang.Object","callees":[]},{"method_name":"__new_array","callees":[]}]}]}
|
@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2016 - present Facebook, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under the BSD style license found in the
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
include ../Makefile
|
||||
|
||||
ANALYZER = infer
|
||||
|
||||
FILES = \
|
||||
BasicHarnessActivity.java \
|
||||
|
||||
compile:
|
||||
javac -cp $(CLASSPATH) $(FILES)
|
||||
|
||||
analyze:
|
||||
$(INFER_BIN) -a $(ANALYZER) --android-harness -- javac -cp $(CLASSPATH) $(FILES) >/dev/null 2>/dev/null
|
@ -0,0 +1 @@
|
||||
BasicHarnessActivity.java, codetoanalyze.java.harness.BasicHarnessActivity.InferGeneratedHarness(), -1, NULL_DEREFERENCE
|
@ -1,24 +0,0 @@
|
||||
tests_dependencies = [
|
||||
'//infer/lib/java/android:android',
|
||||
'//dependencies/java/guava:guava',
|
||||
'//dependencies/java/junit:hamcrest',
|
||||
'//dependencies/java/jackson:jackson',
|
||||
'//dependencies/java/jsr-305:jsr-305',
|
||||
'//dependencies/java/junit:junit',
|
||||
'//dependencies/java/opencsv:opencsv',
|
||||
'//infer/tests/utils:utils',
|
||||
'//infer/tests/codetoanalyze/java/crashcontext:crashcontext',
|
||||
'//infer/tests/codetoanalyze/java/infer:infer',
|
||||
]
|
||||
|
||||
# ############### Java endtoend tests ########################
|
||||
java_test(
|
||||
name='java_endtoend_tests',
|
||||
deps=[
|
||||
'//infer/tests/endtoend/java/crashcontext:crashcontext',
|
||||
'//infer/tests/endtoend/java/harness:harness',
|
||||
],
|
||||
visibility=[
|
||||
'PUBLIC',
|
||||
],
|
||||
)
|
@ -1,16 +0,0 @@
|
||||
java_test(
|
||||
name='crashcontext',
|
||||
srcs=glob(['*.java']),
|
||||
deps=[
|
||||
'//dependencies/java/guava:guava',
|
||||
'//dependencies/java/junit:hamcrest',
|
||||
'//dependencies/java/junit:junit',
|
||||
'//infer/tests/utils:utils',
|
||||
],
|
||||
resources=[
|
||||
'//infer/tests/codetoanalyze/java/crashcontext:analyze',
|
||||
],
|
||||
visibility=[
|
||||
'PUBLIC',
|
||||
],
|
||||
)
|
@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package endtoend.java.crashcontext;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.CrashContextResults;
|
||||
|
||||
public class BranchingCallsTest {
|
||||
|
||||
public static final String TAG = "BranchingCallsExample";
|
||||
public static final String FILENAME = "BranchingCallsExample.java";
|
||||
|
||||
public static final String MAIN_METHOD =
|
||||
"codetoanalyze.java.crashcontext.BranchingCallsExample.main(java.lang.String[]):void";
|
||||
public static final int MAIN_METHOD_LOC_START = 33;
|
||||
public static final int MAIN_METHOD_LOC_LINE = 34;
|
||||
public static final int MAIN_METHOD_LOC_END = 34;
|
||||
|
||||
public static final String FOO_METHOD =
|
||||
"codetoanalyze.java.crashcontext.BranchingCallsExample.foo():void";
|
||||
public static final int FOO_METHOD_LOC_START = 27;
|
||||
public static final int FOO_METHOD_LOC_LINE = 27;
|
||||
public static final int FOO_METHOD_LOC_END = 30;
|
||||
|
||||
public static final String PRE_BAR_METHOD =
|
||||
"codetoanalyze.java.crashcontext.BranchingCallsExample.pre_bar():void";
|
||||
public static final int PRE_BAR_METHOD_LOC_START = 14;
|
||||
public static final int PRE_BAR_METHOD_LOC_LINE = 14;
|
||||
public static final int PRE_BAR_METHOD_LOC_END = 15;
|
||||
|
||||
public static final String BAR_METHOD =
|
||||
"codetoanalyze.java.crashcontext.BranchingCallsExample.bar():void";
|
||||
public static final int BAR_METHOD_LOC_START = 22;
|
||||
public static final int BAR_METHOD_LOC_LINE = 24;
|
||||
public static final int BAR_METHOD_LOC_END = 24;
|
||||
|
||||
public static final String POST_BAR_METHOD =
|
||||
"codetoanalyze.java.crashcontext.BranchingCallsExample.post_bar():void";
|
||||
|
||||
public static final String TO_STRING_METHOD =
|
||||
"java.lang.String.toString():java.lang.String";
|
||||
|
||||
private static CrashContextResults crashcontext;
|
||||
|
||||
@BeforeClass
|
||||
public static void loadResults() throws IOException {
|
||||
crashcontext =
|
||||
CrashContextResults.loadJSONResults(TAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shapeOfTheStack() {
|
||||
assertThat("The stack trace should contain " + BAR_METHOD,
|
||||
crashcontext.hasStackFrame(BAR_METHOD, 0));
|
||||
assertThat("The stack trace should contain " + FOO_METHOD,
|
||||
crashcontext.hasStackFrame(FOO_METHOD, 1));
|
||||
assertThat("The stack trace should contain " + MAIN_METHOD,
|
||||
crashcontext.hasStackFrame(MAIN_METHOD, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringMethodIsFound() {
|
||||
assertThat("Method " + TO_STRING_METHOD + " should be part of the context",
|
||||
crashcontext.hasMethod(TO_STRING_METHOD));
|
||||
assertThat("Method " + TO_STRING_METHOD + " should be reachable in the " +
|
||||
"context tree from " + BAR_METHOD,
|
||||
crashcontext.hasPath(BAR_METHOD, TO_STRING_METHOD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preBarMethodIsFound() {
|
||||
assertThat("Method " + PRE_BAR_METHOD + " should be part of the context",
|
||||
crashcontext.hasMethod(PRE_BAR_METHOD));
|
||||
assertThat("Method " + PRE_BAR_METHOD + " should be reachable in the " +
|
||||
"context tree from " + FOO_METHOD,
|
||||
crashcontext.hasPath(FOO_METHOD, PRE_BAR_METHOD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postBarMethodIsOmitted() {
|
||||
assertThat("Method " + POST_BAR_METHOD + " shouldn't be part of the context",
|
||||
crashcontext.hasNotMethod(POST_BAR_METHOD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sourceFileLocations() {
|
||||
assertThat("Method " + MAIN_METHOD + " should have the following " +
|
||||
"location information: {file: " + FILENAME +
|
||||
", critical line: " + MAIN_METHOD_LOC_LINE +
|
||||
", range start: " + MAIN_METHOD_LOC_START +
|
||||
", range end: " + MAIN_METHOD_LOC_END + "}",
|
||||
crashcontext.hasMethodWithLocation(MAIN_METHOD,
|
||||
FILENAME,
|
||||
MAIN_METHOD_LOC_LINE,
|
||||
MAIN_METHOD_LOC_START,
|
||||
MAIN_METHOD_LOC_END));
|
||||
assertThat("Method " + FOO_METHOD + " should have the following " +
|
||||
"location information: {file: " + FILENAME +
|
||||
", critical line: " + FOO_METHOD_LOC_LINE +
|
||||
", range start: " + FOO_METHOD_LOC_START +
|
||||
", range end: " + FOO_METHOD_LOC_END + "}",
|
||||
crashcontext.hasMethodWithLocation(FOO_METHOD,
|
||||
FILENAME,
|
||||
FOO_METHOD_LOC_LINE,
|
||||
FOO_METHOD_LOC_START,
|
||||
FOO_METHOD_LOC_END));
|
||||
assertThat("Method " + BAR_METHOD + " should have the following " +
|
||||
"location information: {file: " + FILENAME +
|
||||
", critical line: " + BAR_METHOD_LOC_LINE +
|
||||
", range start: " + BAR_METHOD_LOC_START +
|
||||
", range end: " + BAR_METHOD_LOC_END + "}",
|
||||
crashcontext.hasMethodWithLocation(BAR_METHOD,
|
||||
FILENAME,
|
||||
BAR_METHOD_LOC_LINE,
|
||||
BAR_METHOD_LOC_START,
|
||||
BAR_METHOD_LOC_END));
|
||||
assertThat("Method " + PRE_BAR_METHOD + " should have the following " +
|
||||
"location information: {file: " + FILENAME +
|
||||
", critical line: " + PRE_BAR_METHOD_LOC_LINE +
|
||||
", range start: " + PRE_BAR_METHOD_LOC_START +
|
||||
", range end: " + PRE_BAR_METHOD_LOC_END + "}",
|
||||
crashcontext.hasMethodWithLocation(PRE_BAR_METHOD,
|
||||
FILENAME,
|
||||
PRE_BAR_METHOD_LOC_LINE,
|
||||
PRE_BAR_METHOD_LOC_START,
|
||||
PRE_BAR_METHOD_LOC_END));
|
||||
}
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package endtoend.java.crashcontext;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.CrashContextResults;
|
||||
|
||||
public class MethodNameClashTest {
|
||||
|
||||
public static final String TAG = "MethodNameClashExample";
|
||||
|
||||
public static final String MAIN_METHOD =
|
||||
"codetoanalyze.java.crashcontext.MethodNameClashExample.main(java.lang.String[]):void";
|
||||
|
||||
public static final String A_FOO_METHOD =
|
||||
"codetoanalyze.java.crashcontext.MethodNameClashExample$A.foo():void";
|
||||
|
||||
public static final String B_FOO_METHOD =
|
||||
"codetoanalyze.java.crashcontext.MethodNameClashExample$B.foo():void";
|
||||
|
||||
private static CrashContextResults crashcontext;
|
||||
|
||||
@BeforeClass
|
||||
public static void loadResults() throws IOException {
|
||||
crashcontext =
|
||||
CrashContextResults.loadJSONResults(TAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shapeOfTheStack() {
|
||||
assertThat("The stack trace should contain " + A_FOO_METHOD,
|
||||
crashcontext.hasStackFrame(A_FOO_METHOD, 0));
|
||||
assertThat("The stack trace should contain " + B_FOO_METHOD,
|
||||
crashcontext.hasStackFrame(B_FOO_METHOD, 1));
|
||||
assertThat("The stack trace should contain " + MAIN_METHOD,
|
||||
crashcontext.hasStackFrame(MAIN_METHOD, 2));
|
||||
}
|
||||
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package endtoend.java.crashcontext;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.CrashContextResults;
|
||||
|
||||
public class MinimalCrashTest {
|
||||
|
||||
public static final String TAG = "MinimalCrashExample";
|
||||
|
||||
public static final String MAIN_METHOD =
|
||||
"codetoanalyze.java.crashcontext.MinimalCrashExample.main(java.lang.String[]):void";
|
||||
|
||||
public static final String TO_STRING_METHOD =
|
||||
"java.lang.String.toString():java.lang.String";
|
||||
|
||||
private static CrashContextResults crashcontext;
|
||||
|
||||
@BeforeClass
|
||||
public static void loadResults() throws IOException {
|
||||
crashcontext =
|
||||
CrashContextResults.loadJSONResults(TAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shapeOfTheStack() {
|
||||
assertThat("The stack trace should contain " + MAIN_METHOD,
|
||||
crashcontext.hasStackFrame(MAIN_METHOD, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringMethodIsDetected() {
|
||||
assertThat("Method " + TO_STRING_METHOD + " should be part of the context",
|
||||
crashcontext.hasMethod(TO_STRING_METHOD));
|
||||
assertThat("Method " + TO_STRING_METHOD + " should be reachable in the " +
|
||||
"context tree from " + MAIN_METHOD,
|
||||
crashcontext.hasPath(MAIN_METHOD, TO_STRING_METHOD));
|
||||
}
|
||||
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package endtoend.java.crashcontext;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.CrashContextResults;
|
||||
|
||||
public class MultiStackFrameCrashTest {
|
||||
|
||||
public static final String TAG = "MultiStackFrameCrashExample";
|
||||
|
||||
public static final String MAIN_METHOD =
|
||||
"codetoanalyze.java.crashcontext.MultiStackFrameCrashExample.main(java.lang.String[]):void";
|
||||
|
||||
public static final String FOO_METHOD =
|
||||
"codetoanalyze.java.crashcontext.MultiStackFrameCrashExample.foo():void";
|
||||
|
||||
public static final String BAR_METHOD =
|
||||
"codetoanalyze.java.crashcontext.MultiStackFrameCrashExample.bar():void";
|
||||
|
||||
public static final String TO_STRING_METHOD =
|
||||
"java.lang.String.toString():java.lang.String";
|
||||
|
||||
private static CrashContextResults crashcontext;
|
||||
|
||||
@BeforeClass
|
||||
public static void loadResults() throws IOException {
|
||||
crashcontext =
|
||||
CrashContextResults.loadJSONResults(TAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shapeOfTheStack() {
|
||||
assertThat("The stack trace should contain " + BAR_METHOD,
|
||||
crashcontext.hasStackFrame(BAR_METHOD, 0));
|
||||
assertThat("The stack trace should contain " + FOO_METHOD,
|
||||
crashcontext.hasStackFrame(FOO_METHOD, 1));
|
||||
assertThat("The stack trace should contain " + MAIN_METHOD,
|
||||
crashcontext.hasStackFrame(MAIN_METHOD, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringMethodIsFound() {
|
||||
assertThat("Method " + TO_STRING_METHOD + " should be part of the context",
|
||||
crashcontext.hasMethod(TO_STRING_METHOD));
|
||||
assertThat("Method " + TO_STRING_METHOD + " should be reachable in the " +
|
||||
"context tree from " + BAR_METHOD,
|
||||
crashcontext.hasPath(BAR_METHOD, TO_STRING_METHOD));
|
||||
}
|
||||
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package endtoend.java.crashcontext;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.CrashContextResults;
|
||||
|
||||
public class NativeMethodTest {
|
||||
|
||||
public static final String TAG = "NativeMethodExample";
|
||||
|
||||
public static final String MAIN_METHOD =
|
||||
"codetoanalyze.java.crashcontext.NativeMethodExample.main(java.lang.String[]):void";
|
||||
|
||||
// Currently, native methods are missing their arguments lists.
|
||||
public static final String REFLECTION_INVOKE_METHOD =
|
||||
"sun.reflect.NativeMethodAccessorImpl.invoke0";
|
||||
|
||||
public static final String FOO_METHOD =
|
||||
"codetoanalyze.java.crashcontext.NativeMethodExample.foo():void";
|
||||
|
||||
private static CrashContextResults crashcontext;
|
||||
|
||||
@BeforeClass
|
||||
public static void loadResults() throws IOException {
|
||||
crashcontext =
|
||||
CrashContextResults.loadJSONResults(TAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shapeOfTheStack() {
|
||||
assertThat("The stack trace should contain " + FOO_METHOD,
|
||||
crashcontext.hasStackFrame(FOO_METHOD));
|
||||
assertThat("The trace should contain at least one native method ",
|
||||
crashcontext.hasNativeMethodOnStack());
|
||||
assertThat("The stack trace should contain " + REFLECTION_INVOKE_METHOD,
|
||||
crashcontext.hasStackFrame(REFLECTION_INVOKE_METHOD));
|
||||
assertThat("The stack trace should contain " + MAIN_METHOD,
|
||||
crashcontext.hasStackFrame(MAIN_METHOD));
|
||||
}
|
||||
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
java_test(
|
||||
name='harness',
|
||||
srcs=glob(['*.java']),
|
||||
deps=[
|
||||
'//dependencies/java/guava:guava',
|
||||
'//dependencies/java/junit:hamcrest',
|
||||
'//dependencies/java/junit:junit',
|
||||
'//infer/tests/utils:utils',
|
||||
],
|
||||
visibility=[
|
||||
'PUBLIC',
|
||||
],
|
||||
)
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package endtoend.java.harness;
|
||||
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static utils.matchers.ResultContainsErrorNoFilename.contains;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.DebuggableTemporaryFolder;
|
||||
import utils.InferException;
|
||||
import utils.InferResults;
|
||||
import utils.InferRunner;
|
||||
|
||||
public class InhabitTest {
|
||||
|
||||
public static final String TrickyParamsActivity =
|
||||
"infer/tests/codetoanalyze/java/harness/TrickyParamsActivity.java";
|
||||
|
||||
public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE";
|
||||
|
||||
@ClassRule
|
||||
public static DebuggableTemporaryFolder folder = new DebuggableTemporaryFolder();
|
||||
|
||||
private static ImmutableList<String> inferCmd;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void runInfer() throws IOException {
|
||||
inferCmd = InferRunner.createJavaInferHarnessCommand(folder, TrickyParamsActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canInhabitTrickyParams()
|
||||
throws InterruptedException, IOException, InferException {
|
||||
InferResults inferResults = InferRunner.runInferJava(inferCmd);
|
||||
assertThat(
|
||||
"Results should contain NPE",
|
||||
inferResults,
|
||||
contains(
|
||||
NULL_DEREFERENCE,
|
||||
"java.harness.TrickyParamsActivity.InferGeneratedHarness"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package endtoend.java.harness;
|
||||
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static utils.matchers.ResultContainsErrorNoFilename.contains;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.DebuggableTemporaryFolder;
|
||||
import utils.InferException;
|
||||
import utils.InferResults;
|
||||
import utils.InferRunner;
|
||||
|
||||
public class LifecycleTest {
|
||||
|
||||
public static final String BasicHarnessActivity =
|
||||
"infer/tests/codetoanalyze/java/harness/BasicHarnessActivity.java";
|
||||
|
||||
public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE";
|
||||
|
||||
@ClassRule
|
||||
public static DebuggableTemporaryFolder folder = new DebuggableTemporaryFolder();
|
||||
|
||||
private static ImmutableList<String> inferCmd;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void runInfer() throws IOException {
|
||||
inferCmd = InferRunner.createJavaInferHarnessCommand(folder, BasicHarnessActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void harnessRevealsNpe()
|
||||
throws InterruptedException, IOException, InferException {
|
||||
InferResults inferResults = InferRunner.runInferJava(inferCmd);
|
||||
assertThat(
|
||||
"Results should contain NPE",
|
||||
inferResults,
|
||||
contains(
|
||||
NULL_DEREFERENCE,
|
||||
"java.harness.BasicHarnessActivity.InferGeneratedHarness"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
# TODO: this file exists only to support buck integration in infer/tests/build_systems/build_integration_tests.py
|
||||
java_test(
|
||||
name='infer',
|
||||
srcs=glob(['*.java']),
|
||||
deps=[
|
||||
'//dependencies/java/guava:guava',
|
||||
'//dependencies/java/junit:hamcrest',
|
||||
'//dependencies/java/junit:junit',
|
||||
'//infer/tests/utils:utils',
|
||||
],
|
||||
resources=[
|
||||
'//infer/tests/codetoanalyze/java/infer:analyze',
|
||||
],
|
||||
visibility=[
|
||||
'PUBLIC',
|
||||
],
|
||||
)
|
@ -1,35 +0,0 @@
|
||||
tests_dependencies = [
|
||||
'//infer/lib/java/android:android',
|
||||
'//dependencies/java/guava:guava',
|
||||
'//dependencies/java/junit:hamcrest',
|
||||
'//dependencies/java/jackson:jackson',
|
||||
'//dependencies/java/jsr-305:jsr-305',
|
||||
'//dependencies/java/junit:junit',
|
||||
'//dependencies/java/opencsv:opencsv',
|
||||
'//infer/tests/utils:utils',
|
||||
]
|
||||
|
||||
objcpp_infer_test_sources = glob(['*.java'])
|
||||
objcpp_infer_test_deps = []
|
||||
for test_source in objcpp_infer_test_sources:
|
||||
target_name = test_source.replace("/", "_")[:-len(".java")]
|
||||
objcpp_infer_test_deps.append(target_name)
|
||||
|
||||
java_test(
|
||||
name=target_name,
|
||||
srcs=[test_source],
|
||||
deps=tests_dependencies,
|
||||
visibility=[
|
||||
'PUBLIC',
|
||||
],
|
||||
source='7',
|
||||
target='7',
|
||||
)
|
||||
|
||||
java_test(
|
||||
name='infer',
|
||||
deps=[':' + x for x in objcpp_infer_test_deps],
|
||||
visibility=[
|
||||
'PUBLIC',
|
||||
],
|
||||
)
|
@ -1,18 +0,0 @@
|
||||
java_library(
|
||||
name='utils',
|
||||
srcs=glob(['**/*.java']),
|
||||
deps=[
|
||||
'//infer/lib/java/android:android',
|
||||
'//dependencies/java/guava:guava',
|
||||
'//dependencies/java/junit:hamcrest',
|
||||
'//dependencies/java/jackson:jackson',
|
||||
'//dependencies/java/jsr-305:jsr-305',
|
||||
'//dependencies/java/junit:junit',
|
||||
'//dependencies/java/opencsv:opencsv'
|
||||
],
|
||||
visibility = [
|
||||
'PUBLIC',
|
||||
],
|
||||
source='7',
|
||||
target='7',
|
||||
)
|
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
public class CrashContextResults {
|
||||
|
||||
private static final String CRASHCONTEXT_JSON =
|
||||
"/buck-out/gen/infer/tests/codetoanalyze/java/crashcontext/analyze/crashcontext.json";
|
||||
|
||||
private JsonNode json;
|
||||
private String filename;
|
||||
|
||||
private CrashContextResults(String tag) throws IOException {
|
||||
String path =
|
||||
System.getProperty("user.dir") + CRASHCONTEXT_JSON + "." + tag;
|
||||
byte[] jsonData = ByteStreams.toByteArray(new FileInputStream(path));
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
json = objectMapper.readTree(jsonData);
|
||||
}
|
||||
|
||||
public boolean hasStackFrame(String methodSignature, int pos) {
|
||||
return methodSignature.equals(
|
||||
json.path("stack").get(pos).path("method_name").asText());
|
||||
}
|
||||
|
||||
public boolean hasStackFrame(String methodSignature) {
|
||||
for (JsonNode frame : json.path("stack")) {
|
||||
if (methodSignature.equals(frame.path("method_name").asText())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasLocationOnStack(String filename, int line) {
|
||||
for (JsonNode frame : json.path("stack")) {
|
||||
if (filename.equals(frame.path("location").path("file").asText()) &&
|
||||
line == frame.path("location").path("line").asInt()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasNativeMethodOnStack() {
|
||||
for (JsonNode frame : json.path("stack")) {
|
||||
if (frame.path("location").path("file").asText()
|
||||
.equals("Native Method")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<JsonNode> findNodesForMethod(JsonNode node,
|
||||
String methodSignature,
|
||||
List<JsonNode> accumulator) {
|
||||
if (methodSignature.equals(node.path("method_name").asText())) {
|
||||
accumulator.add(node);
|
||||
}
|
||||
for (JsonNode callee : node.path("callees")) {
|
||||
findNodesForMethod(callee, methodSignature, accumulator);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
private List<JsonNode> findNodesForMethod(String methodSignature) {
|
||||
List<JsonNode> accumulator = new ArrayList<JsonNode>();
|
||||
for (JsonNode frame : json.path("stack")) {
|
||||
findNodesForMethod(frame, methodSignature, accumulator);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
public boolean hasMethod(String methodSignature) {
|
||||
return !findNodesForMethod(methodSignature).isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasNotMethod(String methodSignature) {
|
||||
return findNodesForMethod(methodSignature).isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasPath(String methodFrom, String methodTo) {
|
||||
for (JsonNode from : findNodesForMethod(methodFrom)) {
|
||||
if (!findNodesForMethod(from, methodTo, new ArrayList()).isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasMethodWithLocation(String methodSignature, String filename,
|
||||
int line, int start, int end) {
|
||||
for (JsonNode frame : findNodesForMethod(methodSignature)) {
|
||||
if (frame.path("location").path("file").asText().endsWith(filename) &&
|
||||
line == frame.path("location").path("line").asInt()) {
|
||||
for (JsonNode blameRange : frame.path("location").path("blame_range")) {
|
||||
if (blameRange.path("start_line").asInt() == start &&
|
||||
blameRange.path("end_line").asInt() == end) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static CrashContextResults loadJSONResults(String tag) throws IOException {
|
||||
return new CrashContextResults(tag);
|
||||
}
|
||||
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-present Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package utils;
|
||||
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
public class DebuggableTemporaryFolder extends TemporaryFolder {
|
||||
|
||||
private
|
||||
@Nullable
|
||||
String name;
|
||||
private boolean doNotDeleteOnExit;
|
||||
|
||||
public DebuggableTemporaryFolder() {
|
||||
Map<String, String> env = System.getenv();
|
||||
if (env.get("INFER_KEEP_FOLDER") != null) {
|
||||
doNotDeleteOnExit = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If invoked, the directory created by this {@link org.junit.rules.TemporaryFolder} will not be
|
||||
* deleted when the test finishes.
|
||||
*
|
||||
* @return {@code this}
|
||||
*/
|
||||
public DebuggableTemporaryFolder doNotDeleteOnExit() {
|
||||
this.doNotDeleteOnExit = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name to use to identify this {@link org.junit.rules.TemporaryFolder} when writing log messages
|
||||
* to stdout.
|
||||
*
|
||||
* @return {@code this}
|
||||
*/
|
||||
public DebuggableTemporaryFolder setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void after() {
|
||||
if (doNotDeleteOnExit) {
|
||||
String name = this.name == null ? "TemporaryFolder" : this.name;
|
||||
System.out.printf("%s available at %s.\n", name, getRoot());
|
||||
} else {
|
||||
super.after();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.io.IOException;
|
||||
|
||||
public class InferError {
|
||||
|
||||
private String errorType;
|
||||
private Path errorFile;
|
||||
private String errorMethod;
|
||||
private int errorLine;
|
||||
|
||||
public InferError(String errorType, Path errorFile, String errorMethod, int errorLine) {
|
||||
this.errorType = errorType;
|
||||
this.errorMethod = errorMethod;
|
||||
this.errorLine = errorLine;
|
||||
try {
|
||||
this.errorFile = errorFile.toRealPath();
|
||||
} catch (IOException e) {
|
||||
this.errorFile = errorFile;
|
||||
}
|
||||
}
|
||||
|
||||
public InferError(String errorType, Path errorFile, String errorMethod) {
|
||||
this.errorType = errorType;
|
||||
this.errorFile = errorFile;
|
||||
this.errorMethod = errorMethod;
|
||||
this.errorLine = -1;
|
||||
}
|
||||
|
||||
public static InferError inferError(String errorMethod, Path errorFile, String errorType) {
|
||||
return new InferError(errorMethod, errorFile, errorType);
|
||||
}
|
||||
|
||||
public String getErrorType() {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
public String getErrorMethod() {
|
||||
return errorMethod;
|
||||
}
|
||||
|
||||
public Path getErrorFile() {
|
||||
return errorFile;
|
||||
}
|
||||
|
||||
public int getErrorLine() {
|
||||
return errorLine;
|
||||
}
|
||||
|
||||
public String toStringNoLine() {
|
||||
return errorType + " at " + errorFile + ", method " + errorMethod;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (errorLine > 0)
|
||||
return toStringNoLine() + " (line " + errorLine + ")";
|
||||
else return toStringNoLine();
|
||||
}
|
||||
|
||||
public String toStringFileMethod() {
|
||||
return errorFile + ", method " + errorMethod;
|
||||
}
|
||||
|
||||
public String toStringErrorTypeMethod() {
|
||||
return errorType + " at " + errorMethod;
|
||||
}
|
||||
|
||||
public boolean matchType(String type) {
|
||||
return this.errorType.equals(type);
|
||||
}
|
||||
|
||||
public boolean matchFile(Path file) {
|
||||
Path realFile;
|
||||
try {
|
||||
realFile = file.toRealPath();
|
||||
} catch (IOException e) {
|
||||
realFile = file;
|
||||
}
|
||||
return this.errorFile.equals(realFile);
|
||||
}
|
||||
|
||||
public boolean matchMethod(String method) {
|
||||
return this.errorMethod.equals(method);
|
||||
}
|
||||
|
||||
public boolean matchLine(int line) {
|
||||
return this.errorLine < 0 || line < 0
|
||||
|| (this.errorLine == line);
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils;
|
||||
|
||||
|
||||
public class InferException extends RuntimeException {
|
||||
|
||||
public InferException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
}
|
@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils;
|
||||
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringReader;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import au.com.bytecode.opencsv.CSVReader;
|
||||
|
||||
public class InferResults {
|
||||
|
||||
private ImmutableList<String> inferCmd;
|
||||
|
||||
public static final Pattern JAVA_METHOD_NAME = Pattern.compile("(\\.)(.*)(\\()");
|
||||
public static final Pattern C_FUNCTION_NAME = Pattern.compile("(\")(.*)(\")");
|
||||
public static final Pattern OBJC_FUNCTION_NAME = Pattern.compile("(.*)_(.*)");
|
||||
|
||||
private Vector<InferError> errors = new Vector<InferError>();
|
||||
|
||||
InferResults() {
|
||||
this.inferCmd = ImmutableList.of("");
|
||||
}
|
||||
|
||||
InferResults(ImmutableList<String> inferCmd) {
|
||||
this.inferCmd = inferCmd;
|
||||
}
|
||||
|
||||
public void parseInferResultsFromString(Pattern pattern, String errorString)
|
||||
throws IOException, InferException {
|
||||
|
||||
try (CSVReader reader = new CSVReader(new StringReader(errorString))) {
|
||||
List<String[]> lines = reader.readAll();
|
||||
Path root = Paths.get(System.getProperty("user.dir"));
|
||||
|
||||
for (String[] items : lines) {
|
||||
String errorKind = items[1].trim();
|
||||
String errorType = items[2].trim();
|
||||
if (errorKind.equals("ERROR") ||
|
||||
errorType.equals("ASSIGN_POINTER_WARNING") ||
|
||||
errorType.equals("STRONG_DELEGATE_WARNING") ||
|
||||
errorType.equals("DIRECT_ATOMIC_PROPERTY_ACCESS") ||
|
||||
errorType.equals("CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK") ||
|
||||
errorType.equals("REGISTERED_OBSERVER_BEING_DEALLOCATED") ||
|
||||
errorType.equals("GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL") ||
|
||||
errorType.equals("IMMUTABLE_CAST") ||
|
||||
errorType.equals("PARAMETER_NOT_NULL_CHECKED") ||
|
||||
errorType.equals("DANGLING_POINTER_DEREFERENCE") ||
|
||||
errorType.equals("IVAR_NOT_NULL_CHECKED") ||
|
||||
errorType.equals("BAD_POINTER_COMPARISON") ||
|
||||
errorType.equals("Bad_footprint") ||
|
||||
errorType.equals("MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE")) {
|
||||
Integer errorLine = Integer.parseInt(items[5].trim());
|
||||
String procedure = items[6];
|
||||
Path path = Paths.get(items[8]);
|
||||
if (path.isAbsolute()) {
|
||||
path = root.relativize(Paths.get(items[8]));
|
||||
}
|
||||
Matcher methodMatcher = pattern.matcher(procedure);
|
||||
boolean matching = methodMatcher.find();
|
||||
if (matching) {
|
||||
procedure = methodMatcher.group(2);
|
||||
if (procedure == null) {
|
||||
throw new InferException("Unexpected method name structure.");
|
||||
}
|
||||
}
|
||||
procedure = procedure.trim();
|
||||
InferError error = new InferError(errorType, path, procedure, errorLine);
|
||||
errors.add(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void parseJavaInferResultsFromString(String errorString)
|
||||
throws IOException, InferException {
|
||||
parseInferResultsFromString(JAVA_METHOD_NAME, errorString);
|
||||
}
|
||||
|
||||
public void parseCInferResultsFromString(String errorString)
|
||||
throws IOException, InferException {
|
||||
parseInferResultsFromString(C_FUNCTION_NAME, errorString);
|
||||
}
|
||||
|
||||
public void parseObjCInferResultsFromString(String errorString)
|
||||
throws IOException, InferException {
|
||||
parseInferResultsFromString(OBJC_FUNCTION_NAME, errorString);
|
||||
}
|
||||
|
||||
public Vector<InferError> getErrors() {
|
||||
return errors;
|
||||
}
|
||||
|
||||
public String inferCmdToString() {
|
||||
return "Infer command: " + Joiner.on(' ').join(inferCmd);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = "";
|
||||
for (InferError e : errors) {
|
||||
s = s + "\n" + e.toString();
|
||||
}
|
||||
if (s.length() == 0) return "No results.";
|
||||
return s;
|
||||
}
|
||||
|
||||
public void filter(String filename) {
|
||||
Vector<InferError> filtered_errors = new Vector<InferError>();
|
||||
for (InferError error : errors) {
|
||||
if (error.getErrorFile().endsWith(filename)) {
|
||||
filtered_errors.add(error);
|
||||
}
|
||||
}
|
||||
errors = filtered_errors;
|
||||
}
|
||||
|
||||
public static InferResults loadResultsFromReader(
|
||||
BufferedReader reader,
|
||||
String sourceFile,
|
||||
Pattern pattern) {
|
||||
InferResults inferResults = new InferResults();
|
||||
String resultString = "";
|
||||
try {
|
||||
String line = reader.readLine();
|
||||
while (line != null) {
|
||||
resultString += line + "\n";
|
||||
line = reader.readLine();
|
||||
}
|
||||
inferResults.parseInferResultsFromString(
|
||||
pattern,
|
||||
resultString);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e.toString());
|
||||
}
|
||||
inferResults.filter(sourceFile);
|
||||
return inferResults;
|
||||
}
|
||||
|
||||
private static InferResults loadResultsFromPath(Class currentClass, String sourceFile,
|
||||
String csvPath, Pattern procnamePattern) {
|
||||
BufferedReader reader =
|
||||
new BufferedReader(
|
||||
new InputStreamReader(
|
||||
currentClass.getResourceAsStream(csvPath)));
|
||||
return loadResultsFromReader(
|
||||
Preconditions.checkNotNull(reader),
|
||||
sourceFile,
|
||||
procnamePattern);
|
||||
}
|
||||
|
||||
public static InferResults loadInferResults(Class currentClass, String sourceFile) {
|
||||
return loadResultsFromPath(
|
||||
currentClass,
|
||||
sourceFile,
|
||||
"/infer/tests/codetoanalyze/java/infer/report.csv",
|
||||
InferResults.JAVA_METHOD_NAME);
|
||||
}
|
||||
|
||||
public static InferResults loadTracingResults(Class currentClass, String sourceFile) {
|
||||
return loadResultsFromPath(
|
||||
currentClass,
|
||||
sourceFile,
|
||||
"/infer/tests/codetoanalyze/java/tracing/report.csv",
|
||||
InferResults.JAVA_METHOD_NAME);
|
||||
}
|
||||
|
||||
public static InferResults loadTracingComparisonResults(Class currentClass, String sourceFile) {
|
||||
return loadResultsFromPath(
|
||||
currentClass,
|
||||
sourceFile,
|
||||
"/infer/tests/codetoanalyze/java/infer/comparison_report.csv",
|
||||
InferResults.JAVA_METHOD_NAME);
|
||||
}
|
||||
|
||||
public static InferResults loadCInferResults(Class currentClass, String sourceFile) {
|
||||
return loadResultsFromPath(
|
||||
currentClass,
|
||||
sourceFile,
|
||||
"/infer/tests/codetoanalyze/c/errors/report.csv",
|
||||
InferResults.C_FUNCTION_NAME);
|
||||
}
|
||||
|
||||
}
|
@ -1,306 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class InferRunner {
|
||||
|
||||
public static final String BUGS_FILE_NAME = "report.csv";
|
||||
|
||||
public static final String DOT_FILE_NAME = "icfg.dot";
|
||||
|
||||
public static final String CAPTURED_FOLDER = "captured";
|
||||
|
||||
private static File bugsFile;
|
||||
|
||||
@Nullable
|
||||
private static File dotFile;
|
||||
|
||||
private static File resultsDir;
|
||||
|
||||
private static final ImmutableList<String> EMPTY_ARGS = ImmutableList.of();
|
||||
|
||||
private static final String ANDROID =
|
||||
"/infer/lib/java/android/android-19.jar";
|
||||
|
||||
private static final String[] LIBRARIES = {
|
||||
"/infer/lib/java/models.jar",
|
||||
"/infer/annotations/annotations.jar",
|
||||
"/dependencies/java/guava/guava-10.0.1-fork.jar",
|
||||
"/dependencies/java/jackson/jackson-2.2.3.jar",
|
||||
};
|
||||
|
||||
private static HashMap<String, InferResults> inferResultsMap =
|
||||
new HashMap<String, InferResults>();
|
||||
|
||||
private static String getXcodeRoot() throws IOException, InterruptedException {
|
||||
ProcessBuilder pb = new ProcessBuilder("xcode-select", "-p");
|
||||
Process process = pb.start();
|
||||
InputStream is = process.getInputStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr);
|
||||
String line = br.readLine();
|
||||
process.waitFor();
|
||||
return line;
|
||||
}
|
||||
|
||||
private static String getXCodeVersion() throws IOException, InterruptedException {
|
||||
ProcessBuilder pb = new ProcessBuilder("xcodebuild", "-version");
|
||||
Process process = pb.start();
|
||||
InputStream is = process.getInputStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr);
|
||||
String line = br.readLine();
|
||||
process.waitFor();
|
||||
return line;
|
||||
}
|
||||
|
||||
private static ImmutableList<String> createInferJavaCommand(
|
||||
TemporaryFolder folder,
|
||||
ImmutableList<String> sourceFiles,
|
||||
String analyzer,
|
||||
ImmutableList<String> args) {
|
||||
try {
|
||||
File resultsDir = createResultsDir(folder);
|
||||
String resultsDirName = resultsDir.getAbsolutePath();
|
||||
InferRunner.bugsFile = new File(resultsDir, BUGS_FILE_NAME);
|
||||
|
||||
ImmutableList<String> javacCmd = createJavacCommand(
|
||||
folder,
|
||||
sourceFiles);
|
||||
|
||||
return new ImmutableList.Builder<String>()
|
||||
.add("infer")
|
||||
.add("--no-progress-bar")
|
||||
.add("--no-filtering")
|
||||
.addAll(args)
|
||||
.add("-o")
|
||||
.add(resultsDirName)
|
||||
.add("-a")
|
||||
.add(analyzer)
|
||||
.add("--")
|
||||
.addAll(javacCmd)
|
||||
.build();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
return ImmutableList.of(); // unreachable
|
||||
}
|
||||
}
|
||||
|
||||
private static ImmutableList<String> createJavacCommand(
|
||||
TemporaryFolder folder,
|
||||
ImmutableList<String> sourceFiles)
|
||||
throws IOException {
|
||||
File classesDir = folder.newFolder("classes_out");
|
||||
String classesDirName = classesDir.getAbsolutePath();
|
||||
|
||||
ImmutableList<String> javacCmd = new ImmutableList.Builder<String>()
|
||||
.add("javac")
|
||||
.add("-classpath")
|
||||
.add(getClasspath())
|
||||
.add("-bootclasspath")
|
||||
.add(getBootClasspath())
|
||||
.add("-d")
|
||||
.add(classesDirName)
|
||||
.addAll(sourceFiles).build();
|
||||
return javacCmd;
|
||||
}
|
||||
|
||||
public static ImmutableList<String> createJavaInferHarnessCommand(
|
||||
TemporaryFolder folder,
|
||||
ImmutableList<String> sourceFiles) {
|
||||
ImmutableList<String> args = new ImmutableList.Builder<String>()
|
||||
.add("--android-harness")
|
||||
.build();
|
||||
return createInferJavaCommand(folder, sourceFiles, "infer", args);
|
||||
}
|
||||
|
||||
public static ImmutableList<String> createJavaInferHarnessCommand(
|
||||
TemporaryFolder folder,
|
||||
String sourceFile) {
|
||||
return createJavaInferHarnessCommand(folder, ImmutableList.of(sourceFile));
|
||||
}
|
||||
|
||||
public static ImmutableList<String> createJavaInferAngelicHarnessCommand(
|
||||
TemporaryFolder folder,
|
||||
ImmutableList<String> sourceFiles) {
|
||||
ImmutableList<String> args = (new ImmutableList.Builder<String>())
|
||||
.add("--android-harness")
|
||||
.build();
|
||||
return createInferJavaCommand(folder, sourceFiles, "infer", args);
|
||||
}
|
||||
|
||||
private static InferResults runInfer(
|
||||
ImmutableList<String> inferCmd,
|
||||
Language lang)
|
||||
throws IOException, InterruptedException, InferException {
|
||||
String inferCmdString = Joiner.on(' ').join(inferCmd);
|
||||
InferResults results = inferResultsMap.get(inferCmdString);
|
||||
if (results == null) {
|
||||
if (lang == Language.Java) checkLibraries();
|
||||
|
||||
runCommand(inferCmd, TestType.END_TO_END);
|
||||
String errorString = getErrors(bugsFile);
|
||||
results = new InferResults(inferCmd);
|
||||
if (lang == Language.Java)
|
||||
results.parseJavaInferResultsFromString(errorString);
|
||||
else if (lang == Language.C || lang == Language.CPP || lang == Language.ObjCPP)
|
||||
results.parseCInferResultsFromString(errorString);
|
||||
else if (lang == Language.ObjC)
|
||||
results.parseObjCInferResultsFromString(errorString);
|
||||
inferResultsMap.put(inferCmdString, results);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public static InferResults runInferJava(ImmutableList<String> inferCmd)
|
||||
throws IOException, InterruptedException, InferException {
|
||||
return runInfer(inferCmd, Language.Java);
|
||||
}
|
||||
|
||||
public static InferResults runInferC(ImmutableList<String> inferCmd)
|
||||
throws IOException, InterruptedException, InferException {
|
||||
return runInfer(inferCmd, Language.C);
|
||||
}
|
||||
|
||||
public static InferResults runInferCPP(ImmutableList<String> inferCmd)
|
||||
throws IOException, InterruptedException, InferException {
|
||||
return runInfer(inferCmd, Language.CPP);
|
||||
}
|
||||
|
||||
public static InferResults runInferObjC(ImmutableList<String> inferCmd)
|
||||
throws IOException, InterruptedException, InferException {
|
||||
return runInfer(inferCmd, Language.ObjC);
|
||||
}
|
||||
|
||||
public static InferResults runInferObjCPP(ImmutableList<String> inferCmd)
|
||||
throws IOException, InterruptedException, InferException {
|
||||
return runInfer(inferCmd, Language.ObjCPP);
|
||||
}
|
||||
|
||||
|
||||
private static void runCommand(
|
||||
ImmutableList<String> inferCmd,
|
||||
TestType testType)
|
||||
throws IOException, InterruptedException, InferException {
|
||||
ProcessBuilder pb = new ProcessBuilder(inferCmd);
|
||||
|
||||
Map<String, String> env = pb.environment();
|
||||
env.put("INFER_REPORT_CUSTOM_ERROR", "1");
|
||||
|
||||
Process process = pb.start();
|
||||
StringBuilder stderr = new StringBuilder();
|
||||
try (BufferedReader bufferedReader =
|
||||
new BufferedReader(
|
||||
new InputStreamReader(
|
||||
process.getErrorStream()))) {
|
||||
String line = null;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
stderr.append(line + "\n");
|
||||
}
|
||||
}
|
||||
process.waitFor();
|
||||
|
||||
File file = null;
|
||||
if (testType == TestType.END_TO_END) {
|
||||
file = bugsFile;
|
||||
} else if (testType == TestType.FRONTEND) {
|
||||
getDotFile();
|
||||
file = dotFile;
|
||||
}
|
||||
if (file == null || !file.exists()) {
|
||||
String fileNotFoundMessage = file == null ?
|
||||
"" : "\n\nFile " + file + " not found.";
|
||||
throw new InferException(
|
||||
"There was an error while calling Infer." +
|
||||
"\n\nCommand output:\n" + stderr +
|
||||
"\nCommand: " + Joiner.on(' ').join(inferCmd) +
|
||||
fileNotFoundMessage +
|
||||
"\n==========================================================================");
|
||||
}
|
||||
}
|
||||
|
||||
static String getErrors(File file) throws IOException {
|
||||
String s = "";
|
||||
String line = "";
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
|
||||
br.readLine();
|
||||
while ((line = br.readLine()) != null) {
|
||||
s += line + "\n";
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private static String getBootClasspath() {
|
||||
String current_dir = System.getProperty("user.dir");
|
||||
String bootclasspath = current_dir + ANDROID;
|
||||
return bootclasspath;
|
||||
}
|
||||
|
||||
private static String getClasspath() {
|
||||
String current_dir = System.getProperty("user.dir");
|
||||
StringBuilder classpath = new StringBuilder();
|
||||
for (String library : LIBRARIES) {
|
||||
classpath.append(current_dir);
|
||||
classpath.append(library);
|
||||
classpath.append(":");
|
||||
}
|
||||
classpath.deleteCharAt(classpath.length() - 1);
|
||||
return classpath.toString();
|
||||
}
|
||||
|
||||
private static void checkLibraries() throws InferException {
|
||||
String current_dir = System.getProperty("user.dir");
|
||||
for (String lib_file : LIBRARIES) {
|
||||
File lib = new File(current_dir + lib_file);
|
||||
if (!lib.exists()) {
|
||||
throw new InferException("File " + lib_file + " not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static File createResultsDir(TemporaryFolder folder) {
|
||||
try {
|
||||
resultsDir = folder.newFolder("infer_out");
|
||||
return resultsDir;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
return null; // unreachable
|
||||
}
|
||||
}
|
||||
|
||||
private static void getDotFile() {
|
||||
File captured = new File(resultsDir, CAPTURED_FOLDER);
|
||||
if (captured.exists()) {
|
||||
File f = new File(captured, captured.list()[0]);
|
||||
dotFile = new File(f, DOT_FILE_NAME);
|
||||
} else {
|
||||
dotFile = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown=true)
|
||||
public class InferStats {
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown=true)
|
||||
private static class IntFields {
|
||||
@JsonProperty(value = "files")
|
||||
int numFiles;
|
||||
|
||||
@JsonProperty(value = "procedures")
|
||||
int numProcedures;
|
||||
|
||||
@JsonProperty(value = "lines")
|
||||
int numLines;
|
||||
}
|
||||
|
||||
private static class FloatFields {
|
||||
@JsonProperty(value = "reporting_time")
|
||||
float reportingTime;
|
||||
|
||||
@JsonProperty(value = "capture_time")
|
||||
float captureTime;
|
||||
|
||||
@JsonProperty(value = "analysis_time")
|
||||
float analysisTime;
|
||||
|
||||
@JsonProperty(value = "makefile_generation_time")
|
||||
float makefileGenerationTime;
|
||||
}
|
||||
|
||||
@JsonProperty(value = "int")
|
||||
private IntFields intFields;
|
||||
|
||||
@JsonProperty(value = "float")
|
||||
private FloatFields floatFields;
|
||||
|
||||
private static InferStats parseInferStatsFromJson(Reader reader) throws IOException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
InferStats user = mapper.readValue(reader, InferStats.class);
|
||||
return user;
|
||||
}
|
||||
|
||||
public static InferStats loadInferStats(Class currentClass, String sourceDir) throws IOException {
|
||||
BufferedReader reader =
|
||||
new BufferedReader(
|
||||
new InputStreamReader(
|
||||
currentClass.getResourceAsStream(sourceDir + "stats.json")));
|
||||
return parseInferStatsFromJson(reader);
|
||||
}
|
||||
|
||||
public int getNumFiles() {
|
||||
return intFields.numFiles;
|
||||
}
|
||||
|
||||
public int getNumProcedures() {
|
||||
return intFields.numProcedures;
|
||||
}
|
||||
|
||||
public int getNumLines() {
|
||||
return intFields.numLines;
|
||||
}
|
||||
|
||||
public float getReportingTime() {
|
||||
return floatFields.reportingTime;
|
||||
}
|
||||
|
||||
public float getCaptureTime() {
|
||||
return floatFields.captureTime;
|
||||
}
|
||||
|
||||
public float getAnalysisTime() {
|
||||
return floatFields.analysisTime;
|
||||
}
|
||||
|
||||
public float getMakefileGenerationTime() {
|
||||
return floatFields.makefileGenerationTime;
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils;
|
||||
|
||||
public enum Language {
|
||||
Java, C, ObjC, CPP, ObjCPP
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils;
|
||||
|
||||
public enum TestType {
|
||||
END_TO_END, FRONTEND;
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Map;
|
||||
|
||||
public class DotFilesEqual extends BaseMatcher<File> {
|
||||
|
||||
String dotFile;
|
||||
|
||||
public DotFilesEqual(String dotFile) {
|
||||
this.dotFile = dotFile;
|
||||
}
|
||||
|
||||
private StringBuilder diffOutput = new StringBuilder();
|
||||
private String diffCommand = "";
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
File newDotFile = (File) o;
|
||||
Map<String, String> env = System.getenv();
|
||||
if (env.get("INFER_DOT_REPLACE") != null) {
|
||||
diffCommand = "cp " + newDotFile.getAbsolutePath() + " " + dotFile;
|
||||
} else {
|
||||
diffCommand = "diff -u " + dotFile + " " + newDotFile.getAbsolutePath();
|
||||
}
|
||||
Process diff_process = null;
|
||||
try {
|
||||
diff_process = Runtime.getRuntime().exec(diffCommand);
|
||||
try (BufferedReader inputReader =
|
||||
new BufferedReader(new InputStreamReader(diff_process.getInputStream()));
|
||||
BufferedReader errorReader =
|
||||
new BufferedReader(new InputStreamReader(diff_process.getErrorStream()))) {
|
||||
|
||||
String line = inputReader.readLine();
|
||||
while (line != null) {
|
||||
diffOutput = diffOutput.append(line + "\n");
|
||||
line = inputReader.readLine();
|
||||
}
|
||||
String errorLine = errorReader.readLine();
|
||||
while (errorLine != null) {
|
||||
diffOutput = diffOutput.append(errorLine + "\n");
|
||||
errorLine = errorReader.readLine();
|
||||
}
|
||||
diff_process.waitFor();
|
||||
return "".equals(diffOutput.toString());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} finally {
|
||||
if (diff_process != null) diff_process.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("Dot file equal to " + dotFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
String outputDesc = "The command:\n\n " + diffCommand
|
||||
+ "\n\nfailed with output:\n" + diffOutput.toString() + "\n";
|
||||
description.appendText(outputDesc);
|
||||
}
|
||||
|
||||
public static <T> Matcher<File> dotFileEqualTo(String dotFile) {
|
||||
return new DotFilesEqual(dotFile);
|
||||
}
|
||||
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import utils.InferError;
|
||||
|
||||
public class ErrorPattern {
|
||||
|
||||
private final String errorType;
|
||||
|
||||
private final Path errorFile;
|
||||
|
||||
private final String errorMethod;
|
||||
|
||||
public ErrorPattern(String type, String file, String method) {
|
||||
errorType = type;
|
||||
errorFile = Paths.get(file);
|
||||
errorMethod = method;
|
||||
}
|
||||
|
||||
String getErrorType() {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
Path getErrorFile() {
|
||||
return errorFile;
|
||||
}
|
||||
|
||||
String getErrorMethod() {
|
||||
return errorMethod;
|
||||
}
|
||||
|
||||
public boolean match(InferError error) {
|
||||
return error.matchType(errorType)
|
||||
&& error.matchMethod(errorMethod)
|
||||
&& error.matchFile(errorFile);
|
||||
}
|
||||
|
||||
public static List<ErrorPattern> createPatterns(String type, String file, String[] methods) {
|
||||
List<ErrorPattern> patterns = new ArrayList<>();
|
||||
for (String method : methods) {
|
||||
patterns.add(new ErrorPattern(type, file, method));
|
||||
}
|
||||
return patterns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getErrorType() + " in file: " + getErrorFile() + ", method: " + getErrorMethod();
|
||||
}
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import utils.InferError;
|
||||
import utils.InferStats;
|
||||
|
||||
public class NumberOfFilesAnalyzed extends BaseMatcher<InferStats> {
|
||||
|
||||
private int expectedNumFiles;
|
||||
private int actualNumFiles;
|
||||
|
||||
public NumberOfFilesAnalyzed(int expectedNumFiles) {
|
||||
this.expectedNumFiles = expectedNumFiles;
|
||||
this.actualNumFiles = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
InferStats stats = (InferStats) o;
|
||||
actualNumFiles = stats.getNumFiles();
|
||||
return actualNumFiles == expectedNumFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(expectedNumFiles + " files analyzed by Infer.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
InferStats stats = (InferStats) item;
|
||||
description.appendText("found " + actualNumFiles + " files analyzed by Infer.");
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferStats> numberOfFilesAnalyzed(
|
||||
int expectedNumFiles) {
|
||||
return new NumberOfFilesAnalyzed(expectedNumFiles);
|
||||
}
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import utils.InferError;
|
||||
import utils.InferStats;
|
||||
|
||||
public class NumberOfProceduresAnalyzed extends BaseMatcher<InferStats> {
|
||||
|
||||
private int expectedNumProcedures;
|
||||
private int actualNumProcedures;
|
||||
|
||||
public NumberOfProceduresAnalyzed(int expectedNumProcedures) {
|
||||
this.expectedNumProcedures = expectedNumProcedures;
|
||||
this.actualNumProcedures = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
InferStats stats = (InferStats) o;
|
||||
actualNumProcedures = stats.getNumProcedures();
|
||||
return actualNumProcedures == expectedNumProcedures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(expectedNumProcedures + " procedures analyzed by Infer.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
InferStats stats = (InferStats) item;
|
||||
description.appendText("found " + actualNumProcedures + " procedures analyzed by Infer.");
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferStats> numberOfProceduresAnalyzed(
|
||||
int expectedNumProcedures) {
|
||||
return new NumberOfProceduresAnalyzed(expectedNumProcedures);
|
||||
}
|
||||
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import utils.InferError;
|
||||
import utils.InferResults;
|
||||
|
||||
public class ResultContainsErrorInMethod extends BaseMatcher<InferResults> {
|
||||
|
||||
private String errorType;
|
||||
private Path errorFile;
|
||||
private String errorMethod;
|
||||
|
||||
public ResultContainsErrorInMethod(String type, String file, String method) {
|
||||
this.errorType = type;
|
||||
this.errorFile = Paths.get(file);
|
||||
this.errorMethod = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
InferResults results = (InferResults) o;
|
||||
for (InferError foundError : results.getErrors()) {
|
||||
if (foundError.matchType(this.errorType)
|
||||
&& foundError.matchMethod(this.errorMethod)
|
||||
&& foundError.matchFile(this.errorFile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(
|
||||
this.errorType + " error in file: " + this.errorFile
|
||||
+ ", method: " + this.errorMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
InferResults results = (InferResults) item;
|
||||
String resultsString = "";
|
||||
for (InferError error : results.getErrors()) {
|
||||
resultsString = resultsString + "\n\t" + error;
|
||||
}
|
||||
description.appendText(
|
||||
"Found errors: \n" + resultsString
|
||||
+ "\nwith:\n" + results.inferCmdToString());
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> contains(String type, String file, String method) {
|
||||
return new ResultContainsErrorInMethod(type, file, method);
|
||||
}
|
||||
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import utils.InferError;
|
||||
import utils.InferResults;
|
||||
|
||||
public class ResultContainsErrorNoFilename extends BaseMatcher<InferResults> {
|
||||
|
||||
private String errorType;
|
||||
private String errorMethod;
|
||||
|
||||
public ResultContainsErrorNoFilename(String type, String method) {
|
||||
this.errorType = type;
|
||||
this.errorMethod = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
InferResults results = (InferResults) o;
|
||||
for (InferError foundError : results.getErrors()) {
|
||||
if (foundError.matchType(this.errorType)
|
||||
&& foundError.matchMethod(this.errorMethod)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(
|
||||
this.errorType + " error in " + this.errorMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
InferResults results = (InferResults) item;
|
||||
String resultsString = "";
|
||||
for (InferError error : results.getErrors()) {
|
||||
resultsString = resultsString + "\n\t" + error;
|
||||
}
|
||||
description.appendText(
|
||||
"Found errors: \n" + resultsString
|
||||
+ "\nwith:\n" + results.inferCmdToString());
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> contains(String type, String method) {
|
||||
return new ResultContainsErrorNoFilename(type, method);
|
||||
}
|
||||
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import utils.InferResults;
|
||||
|
||||
public class ResultContainsExactly extends BaseMatcher<InferResults> {
|
||||
|
||||
Matcher<InferResults> containsAll;
|
||||
Matcher<InferResults> containsOnly;
|
||||
|
||||
private ResultContainsExactly(List<ErrorPattern> patterns) {
|
||||
containsAll = ResultContainsTheseErrors.contains(patterns);
|
||||
containsOnly = ResultContainsOnlyTheseErrors.containsOnly(patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
return containsAll.matches(o) && containsOnly.matches(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
containsAll.describeTo(description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
if (!containsAll.matches(item)) {
|
||||
containsAll.describeMismatch(item, description);
|
||||
}
|
||||
if (!containsOnly.matches(item)) {
|
||||
containsOnly.describeMismatch(item, description);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> containsExactly(List<ErrorPattern> patterns) {
|
||||
return new ResultContainsExactly(patterns);
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> containsExactly(
|
||||
String type,
|
||||
String file,
|
||||
String[] methods) {
|
||||
ArrayList<ErrorPattern> patterns = new ArrayList<>();
|
||||
for (String method : methods) {
|
||||
patterns.add(new ErrorPattern(type, file, method));
|
||||
}
|
||||
return new ResultContainsExactly(patterns);
|
||||
}
|
||||
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Vector;
|
||||
|
||||
import utils.InferError;
|
||||
import utils.InferResults;
|
||||
|
||||
public class ResultContainsLineNumbers extends BaseMatcher<InferResults> {
|
||||
|
||||
private int[] lines;
|
||||
private boolean strict;
|
||||
private Optional<String> bugType;
|
||||
|
||||
public ResultContainsLineNumbers(
|
||||
int[] lines,
|
||||
boolean strict,
|
||||
Optional<String> bugType) {
|
||||
this.lines = lines;
|
||||
this.strict = strict;
|
||||
this.bugType = bugType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
Vector<InferError> errors = ((InferResults) o).getErrors();
|
||||
if (strict && lines.length != errors.size()) {
|
||||
return false;
|
||||
}
|
||||
boolean allContained = true;
|
||||
for (int line : lines) {
|
||||
boolean isContained = false;
|
||||
for (InferError error : errors) {
|
||||
String bugType = this.bugType.or(error.getErrorType());
|
||||
boolean isSameErrType = bugType.equals(error.getErrorType());
|
||||
isContained = isContained || (line == error.getErrorLine() && isSameErrType);
|
||||
}
|
||||
allContained = allContained && isContained;
|
||||
}
|
||||
return allContained;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("Correct line numbers in the error report.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
InferResults results = (InferResults) item;
|
||||
String linesString = Arrays.toString(lines);
|
||||
String reportedLinesString = Arrays.toString(findLineNumbersInReport(results));
|
||||
description.appendText(
|
||||
"Infer did not report an error in the following lines: " + linesString +
|
||||
". \n \t Reported lines are: " + reportedLinesString +
|
||||
"\n" + results.inferCmdToString());
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> containsLines(int[] lines) {
|
||||
return new ResultContainsLineNumbers(lines, false, Optional.<String>absent());
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> containsOnlyLines(int[] lines) {
|
||||
return new ResultContainsLineNumbers(lines, true, Optional.<String>absent());
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> containsLinesOfError(int[] lines, String bugType) {
|
||||
return new ResultContainsLineNumbers(lines, false, Optional.of(bugType));
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> containsOnlyLinesOfError(int[] lines, String bugType) {
|
||||
return new ResultContainsLineNumbers(lines, true, Optional.of(bugType));
|
||||
}
|
||||
|
||||
private int[] findLineNumbersInReport(InferResults results) {
|
||||
Vector<InferError> errors = results.getErrors();
|
||||
int nErrors = errors.size();
|
||||
int[] lines = new int[nErrors];
|
||||
for (int i = 0; i < nErrors; i++) {
|
||||
lines[i] = errors.get(i).getErrorLine();
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import utils.InferError;
|
||||
import utils.InferResults;
|
||||
|
||||
public class ResultContainsNoErrorInMethod extends BaseMatcher<InferResults> {
|
||||
|
||||
ErrorPattern pattern;
|
||||
|
||||
public ResultContainsNoErrorInMethod(String type, String file, String method) {
|
||||
pattern = new ErrorPattern(type, file, method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
InferResults results = (InferResults) o;
|
||||
for (InferError foundError : results.getErrors()) {
|
||||
if (pattern.match(foundError)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(
|
||||
"No " + pattern.getErrorType() + " error in " + pattern.getErrorMethod());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
InferResults results = (InferResults) item;
|
||||
description.appendText(
|
||||
pattern.getErrorType() + " error found in " +
|
||||
pattern.getErrorMethod() + " in the results of Infer.\n" +
|
||||
results.inferCmdToString());
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> doesNotContain(String type, String file, String method) {
|
||||
return new ResultContainsNoErrorInMethod(type, file, method);
|
||||
}
|
||||
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import utils.InferError;
|
||||
import utils.InferResults;
|
||||
|
||||
public class ResultContainsNumberOfErrorsInMethod extends BaseMatcher<InferResults> {
|
||||
|
||||
private final ErrorPattern pattern;
|
||||
private final int numberOfErrors;
|
||||
int actualNumberErrors;
|
||||
|
||||
public ResultContainsNumberOfErrorsInMethod(
|
||||
String type,
|
||||
String file,
|
||||
String method,
|
||||
int numberOfErrors) {
|
||||
this.pattern = new ErrorPattern(type, file, method);
|
||||
this.numberOfErrors = numberOfErrors;
|
||||
this.actualNumberErrors = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
InferResults results = (InferResults) o;
|
||||
for (InferError error : results.getErrors()) {
|
||||
if (pattern.match(error)) {
|
||||
actualNumberErrors++;
|
||||
}
|
||||
}
|
||||
return (actualNumberErrors == numberOfErrors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(
|
||||
numberOfErrors + " " + pattern.getErrorType()
|
||||
+ " errors in file: " + pattern.getErrorFile()
|
||||
+ ", method: " + pattern.getErrorMethod());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
InferResults results = (InferResults) item;
|
||||
description.appendText(
|
||||
actualNumberErrors + " " + pattern.getErrorType() +
|
||||
" errors found in " + pattern.getErrorMethod() + " in the results of Infer." +
|
||||
"\n" + results.inferCmdToString());
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> containsNumberOfErrors(
|
||||
String type,
|
||||
String file,
|
||||
String method,
|
||||
int numberOfErrors) {
|
||||
return new ResultContainsNumberOfErrorsInMethod(type, file, method, numberOfErrors);
|
||||
}
|
||||
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import utils.InferError;
|
||||
import utils.InferResults;
|
||||
|
||||
public class ResultContainsOnlyTheseErrors extends BaseMatcher<InferResults> {
|
||||
|
||||
private List<ErrorPattern> patterns;
|
||||
|
||||
public ResultContainsOnlyTheseErrors(List<ErrorPattern> patterns) {
|
||||
this.patterns = patterns;
|
||||
}
|
||||
|
||||
private boolean mathTypeAndAnyMethod(InferError e) {
|
||||
for (ErrorPattern pattern : patterns) {
|
||||
if (pattern.match(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
InferResults results = (InferResults) o;
|
||||
for (InferError error : results.getErrors()) {
|
||||
if (!mathTypeAndAnyMethod(error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
String errorsString = "";
|
||||
for (ErrorPattern pattern : patterns) {
|
||||
errorsString =
|
||||
errorsString + "\t" + pattern.toString() + "\n";
|
||||
}
|
||||
description.appendText("Only these errors: \n" + errorsString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
InferResults results = (InferResults) item;
|
||||
String unexpectedErrors = "";
|
||||
|
||||
for (InferError error : results.getErrors()) {
|
||||
if (!mathTypeAndAnyMethod(error)) {
|
||||
unexpectedErrors = unexpectedErrors + "\t" + error + "\n";
|
||||
}
|
||||
}
|
||||
description.appendText(
|
||||
"Infer reported the following unexpected errors: \n" +
|
||||
unexpectedErrors + "\n" + results.inferCmdToString());
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> containsOnly(String type, String file, String[] methods) {
|
||||
ArrayList<ErrorPattern> patterns = new ArrayList<>();
|
||||
for (String method : methods) {
|
||||
patterns.add(new ErrorPattern(type, file, method));
|
||||
}
|
||||
return new ResultContainsOnlyTheseErrors(patterns);
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> containsOnly(List<ErrorPattern> patterns) {
|
||||
return new ResultContainsOnlyTheseErrors(patterns);
|
||||
}
|
||||
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import utils.InferError;
|
||||
import utils.InferResults;
|
||||
|
||||
public class ResultContainsTheseErrors extends BaseMatcher<InferResults> {
|
||||
|
||||
private List<ErrorPattern> patterns;
|
||||
|
||||
private ResultContainsTheseErrors(List<ErrorPattern> patterns) {
|
||||
this.patterns = patterns;
|
||||
}
|
||||
|
||||
private boolean patternFound(ErrorPattern pattern, InferResults results) {
|
||||
for (InferError error : results.getErrors()) {
|
||||
if (pattern.match(error)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
InferResults results = (InferResults) o;
|
||||
for (ErrorPattern pattern : patterns) {
|
||||
if (!patternFound(pattern, results)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
String errorsString = "";
|
||||
for (ErrorPattern pattern : patterns) {
|
||||
errorsString += "\t" + pattern.toString() + "\n";
|
||||
}
|
||||
description.appendText("Expecting these errors: \n" + errorsString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
|
||||
InferResults results = (InferResults) item;
|
||||
String expectedErrors = "";
|
||||
|
||||
for (ErrorPattern pattern : patterns) {
|
||||
if (!patternFound(pattern, results)) {
|
||||
expectedErrors += "\t" + pattern.toString() + "\n";
|
||||
}
|
||||
}
|
||||
description.appendText(
|
||||
"The following errors were not reported: \n" + expectedErrors + "\n" + "but found: " +
|
||||
results.toString() + "\n");
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> contains(List<ErrorPattern> patterns) {
|
||||
return new ResultContainsTheseErrors(patterns);
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> contains(String type, String file, String[] methods) {
|
||||
ArrayList<ErrorPattern> patterns = new ArrayList<>();
|
||||
for (String method : methods) {
|
||||
patterns.add(new ErrorPattern(type, file, method));
|
||||
}
|
||||
return new ResultContainsTheseErrors(patterns);
|
||||
}
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package utils.matchers;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import utils.InferError;
|
||||
import utils.InferResults;
|
||||
|
||||
public class ResultContainsZeroErrorsInMethod extends BaseMatcher<InferResults> {
|
||||
|
||||
String fileName;
|
||||
String methodName;
|
||||
int actualNumberErrors;
|
||||
|
||||
public ResultContainsZeroErrorsInMethod(String fileName, String methodName) {
|
||||
this.fileName = fileName;
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
InferResults results = (InferResults) o;
|
||||
for (InferError error : results.getErrors()) {
|
||||
if (fileName.equals(error.getErrorFile()) &&
|
||||
methodName.equals(error.getErrorMethod())) {
|
||||
actualNumberErrors++;
|
||||
}
|
||||
}
|
||||
return actualNumberErrors == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(actualNumberErrors + " errors found in method." + methodName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeMismatch(Object item, Description description) {
|
||||
InferResults results = (InferResults) item;
|
||||
description.appendText(
|
||||
actualNumberErrors + " errors found in " + methodName +
|
||||
" in the results of Infer, but expected 0." + "\n" + results.inferCmdToString());
|
||||
}
|
||||
|
||||
public static <T> Matcher<InferResults> containsZeroErrors(String fileName, String methodName) {
|
||||
return new ResultContainsZeroErrorsInMethod(fileName, methodName);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in new issue