From 7987d1a2a6f3945c9232aee98fe852c011804d37 Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Tue, 25 Aug 2015 08:56:57 -0600 Subject: [PATCH] [Infer][tests] Adding tests for incremental functionality Summary: using the json stats parsing + some BUCK magic to write tests for the incremental mode. --- .../tests/codetoanalyze/java/incremental/BUCK | 11 ++++ .../java/incremental/child_changed/BUCK | 46 ++++++++++++++ .../java/incremental/child_changed/Child.java | 22 +++++++ .../incremental/child_changed/Child.java.v1 | 22 +++++++ .../incremental/child_changed/Child.java.v2 | 22 +++++++ .../child_changed/Grandparent.java | 20 ++++++ .../incremental/child_changed/Parent.java | 24 ++++++++ .../java/incremental/file_unchanged/BUCK | 35 +++++++++++ .../java/incremental/file_unchanged/File.java | 17 ++++++ .../java/incremental/parent_changed/BUCK | 46 ++++++++++++++ .../incremental/parent_changed/Child.java | 17 ++++++ .../incremental/parent_changed/Parent.java.v1 | 20 ++++++ .../incremental/parent_changed/Parent.java.v2 | 24 ++++++++ infer/tests/endtoend/BUCK | 2 + infer/tests/endtoend/java/incremental/BUCK | 18 ++++++ .../java/incremental/ChildChangedTest.java | 48 +++++++++++++++ .../java/incremental/FileUnchangedTest.java | 57 +++++++++++++++++ .../java/incremental/ParentChangedTest.java | 61 +++++++++++++++++++ infer/tests/utils/InferStats.java | 1 + 19 files changed, 513 insertions(+) create mode 100644 infer/tests/codetoanalyze/java/incremental/BUCK create mode 100644 infer/tests/codetoanalyze/java/incremental/child_changed/BUCK create mode 100644 infer/tests/codetoanalyze/java/incremental/child_changed/Child.java create mode 100644 infer/tests/codetoanalyze/java/incremental/child_changed/Child.java.v1 create mode 100644 infer/tests/codetoanalyze/java/incremental/child_changed/Child.java.v2 create mode 100644 infer/tests/codetoanalyze/java/incremental/child_changed/Grandparent.java create mode 100644 infer/tests/codetoanalyze/java/incremental/child_changed/Parent.java create mode 100644 infer/tests/codetoanalyze/java/incremental/file_unchanged/BUCK create mode 100644 infer/tests/codetoanalyze/java/incremental/file_unchanged/File.java create mode 100644 infer/tests/codetoanalyze/java/incremental/parent_changed/BUCK create mode 100644 infer/tests/codetoanalyze/java/incremental/parent_changed/Child.java create mode 100644 infer/tests/codetoanalyze/java/incremental/parent_changed/Parent.java.v1 create mode 100644 infer/tests/codetoanalyze/java/incremental/parent_changed/Parent.java.v2 create mode 100644 infer/tests/endtoend/java/incremental/BUCK create mode 100644 infer/tests/endtoend/java/incremental/ChildChangedTest.java create mode 100644 infer/tests/endtoend/java/incremental/FileUnchangedTest.java create mode 100644 infer/tests/endtoend/java/incremental/ParentChangedTest.java diff --git a/infer/tests/codetoanalyze/java/incremental/BUCK b/infer/tests/codetoanalyze/java/incremental/BUCK new file mode 100644 index 000000000..7e40ea68d --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/BUCK @@ -0,0 +1,11 @@ +java_test( + name='incremental', + deps=[ + '//infer/tests/codetoanalyze/java/incremental/file_unchanged:file_unchanged', + '//infer/tests/codetoanalyze/java/incremental/parent_changed:parent_changed', + '//infer/tests/codetoanalyze/java/incremental/child_changed:child_changed', + ], + visibility = [ + 'PUBLIC' + ] +) diff --git a/infer/tests/codetoanalyze/java/incremental/child_changed/BUCK b/infer/tests/codetoanalyze/java/incremental/child_changed/BUCK new file mode 100644 index 000000000..08bbd3985 --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/child_changed/BUCK @@ -0,0 +1,46 @@ +v1_files = glob([ '**/*.java.v1']) +v2_files = glob(['**/*.java.v2']) +normal_files = glob(['**/*.java']) +sources = v1_files + v2_files + normal_files + +java_library( + name = 'child_changed', + srcs = sources, + deps = [], + visibility = [ + 'PUBLIC' + ] +) + +def copy_files_strip_suffix_cmd(sfx, files): + return ' && '.join([' '.join(['cp', f, f.replace(sfx, '')]) for f in files]) + +out = 'out' +clean_cmd = ' '.join(['rm', '-rf', out]) +stripped_suffix_files = map(lambda f: f.replace('.v1', ''), v1_files) +to_compile = ' '.join(normal_files + stripped_suffix_files) +infer_cmd = ' '.join([ + 'infer', + '-i', + '--absolute-paths', + '-o', out, + '-a', 'infer', + '--', + 'javac', + to_compile +]) +v1_copy_cmd = copy_files_strip_suffix_cmd('.v1', v1_files) +v2_copy_cmd = copy_files_strip_suffix_cmd('.v2', v2_files) +stats_copy_cmd = ' '.join(['cp', out + '/stats.json', '$OUT']) +command = ' && '.join([clean_cmd, v1_copy_cmd, infer_cmd, v2_copy_cmd, infer_cmd, stats_copy_cmd]) + +genrule( + name = 'analyze', + srcs = sources, + out = 'stats.json', + cmd = command, + deps = [':child_changed'], + visibility = [ + 'PUBLIC', + ] +) diff --git a/infer/tests/codetoanalyze/java/incremental/child_changed/Child.java b/infer/tests/codetoanalyze/java/incremental/child_changed/Child.java new file mode 100644 index 000000000..5a7824c82 --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/child_changed/Child.java @@ -0,0 +1,22 @@ +/* +* 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 codetoanalyze.java.incremental.child_changed; + +class Child { + + Object bar() { + return null; + } + + Object dontReanalyze(Object o) { + return o; + } + +} diff --git a/infer/tests/codetoanalyze/java/incremental/child_changed/Child.java.v1 b/infer/tests/codetoanalyze/java/incremental/child_changed/Child.java.v1 new file mode 100644 index 000000000..c76d649dd --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/child_changed/Child.java.v1 @@ -0,0 +1,22 @@ +/* +* 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 codetoanalyze.java.incremental.child_changed; + +class Child { + + Object bar() { + return new Object(); + } + + Object dontReanalyze(Object o) { + return o; + } + +} diff --git a/infer/tests/codetoanalyze/java/incremental/child_changed/Child.java.v2 b/infer/tests/codetoanalyze/java/incremental/child_changed/Child.java.v2 new file mode 100644 index 000000000..5a7824c82 --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/child_changed/Child.java.v2 @@ -0,0 +1,22 @@ +/* +* 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 codetoanalyze.java.incremental.child_changed; + +class Child { + + Object bar() { + return null; + } + + Object dontReanalyze(Object o) { + return o; + } + +} diff --git a/infer/tests/codetoanalyze/java/incremental/child_changed/Grandparent.java b/infer/tests/codetoanalyze/java/incremental/child_changed/Grandparent.java new file mode 100644 index 000000000..d64b9f778 --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/child_changed/Grandparent.java @@ -0,0 +1,20 @@ +/* +* 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 codetoanalyze.java.incremental.child_changed; + +class Grandparent { + + void baz() { + Parent p = new Parent(); + Object o = p.foo(); + o.toString(); + } + +} diff --git a/infer/tests/codetoanalyze/java/incremental/child_changed/Parent.java b/infer/tests/codetoanalyze/java/incremental/child_changed/Parent.java new file mode 100644 index 000000000..67ac15ac9 --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/child_changed/Parent.java @@ -0,0 +1,24 @@ +/* +* 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 codetoanalyze.java.incremental.child_changed; + +class Parent { + + Object foo() { + Child c = new Child(); + Object o = c.bar(); + return o; + } + + void dontReanalyze() { + Object o1 = new Object(); + } + +} diff --git a/infer/tests/codetoanalyze/java/incremental/file_unchanged/BUCK b/infer/tests/codetoanalyze/java/incremental/file_unchanged/BUCK new file mode 100644 index 000000000..6f759af7f --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/file_unchanged/BUCK @@ -0,0 +1,35 @@ +sources = glob([ '**/*.java']) + +java_library( + name = 'file_unchanged', + srcs = sources, + visibility = [ + 'PUBLIC' + ] +) + +out = 'out' +clean_cmd = ' '.join(['rm', '-rf', out]) +infer_cmd = ' '.join([ + 'infer', + '-i', + '--absolute-paths', + '-o', out, + '-a', 'infer', + '--', + 'javac', + '$SRCS', +]) +stats_copy_cmd = ' '.join(['cp', out + '/stats.json', '$OUT']) +command = ' && '.join([clean_cmd, infer_cmd, infer_cmd, stats_copy_cmd]) + +genrule( + name = 'analyze', + srcs = sources, + out = 'stats.json', + cmd = command, + deps = [':file_unchanged'], + visibility = [ + 'PUBLIC', + ] +) diff --git a/infer/tests/codetoanalyze/java/incremental/file_unchanged/File.java b/infer/tests/codetoanalyze/java/incremental/file_unchanged/File.java new file mode 100644 index 000000000..d2f801687 --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/file_unchanged/File.java @@ -0,0 +1,17 @@ +/* +* 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 codetoanalyze.java.incremental.file_unchanged; + +public class File { + + Object o() { + return new Object(); + } +} diff --git a/infer/tests/codetoanalyze/java/incremental/parent_changed/BUCK b/infer/tests/codetoanalyze/java/incremental/parent_changed/BUCK new file mode 100644 index 000000000..781b49c20 --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/parent_changed/BUCK @@ -0,0 +1,46 @@ +v1_files = glob([ '**/*.java.v1']) +v2_files = glob(['**/*.java.v2']) +normal_files = glob(['**/*.java']) +sources = v1_files + v2_files + normal_files + +java_library( + name = 'parent_changed', + srcs = sources, + deps = [], + visibility = [ + 'PUBLIC' + ] +) + +def copy_files_strip_suffix_cmd(sfx, files): + return ' && '.join([' '.join(['cp', f, f.replace(sfx, '')]) for f in files]) + +out = 'out' +clean_cmd = ' '.join(['rm', '-rf', out]) +stripped_suffix_files = map(lambda f: f.replace('.v1', ''), v1_files) +to_compile = ' '.join(normal_files + stripped_suffix_files) +infer_cmd = ' '.join([ + 'infer', + '-i', + '--absolute-paths', + '-o', out, + '-a', 'infer', + '--', + 'javac', + to_compile +]) +v1_copy_cmd = copy_files_strip_suffix_cmd('.v1', v1_files) +v2_copy_cmd = copy_files_strip_suffix_cmd('.v2', v2_files) +stats_copy_cmd = ' '.join(['cp', out + '/stats.json', '$OUT']) +command = ' && '.join([clean_cmd, v1_copy_cmd, infer_cmd, v2_copy_cmd, infer_cmd, stats_copy_cmd]) + +genrule( + name = 'analyze', + srcs = sources, + out = 'stats.json', + cmd = command, + deps = [':parent_changed'], + visibility = [ + 'PUBLIC', + ] +) diff --git a/infer/tests/codetoanalyze/java/incremental/parent_changed/Child.java b/infer/tests/codetoanalyze/java/incremental/parent_changed/Child.java new file mode 100644 index 000000000..4f722e689 --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/parent_changed/Child.java @@ -0,0 +1,17 @@ +/* +* 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 codetoanalyze.java.incremental.parent_changed; + +class Child { + + Object bar() { + return new Object(); + } +} diff --git a/infer/tests/codetoanalyze/java/incremental/parent_changed/Parent.java.v1 b/infer/tests/codetoanalyze/java/incremental/parent_changed/Parent.java.v1 new file mode 100644 index 000000000..cc93f2a13 --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/parent_changed/Parent.java.v1 @@ -0,0 +1,20 @@ +/* +* 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 codetoanalyze.java.incremental.parent_changed; + +class Parent { + + void foo() { + Child c = new Child(); + Object o = c.bar(); + o.toString(); + } + +} diff --git a/infer/tests/codetoanalyze/java/incremental/parent_changed/Parent.java.v2 b/infer/tests/codetoanalyze/java/incremental/parent_changed/Parent.java.v2 new file mode 100644 index 000000000..4c3d246e2 --- /dev/null +++ b/infer/tests/codetoanalyze/java/incremental/parent_changed/Parent.java.v2 @@ -0,0 +1,24 @@ +/* +* 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 codetoanalyze.java.incremental.parent_changed; + +class Parent { + + void foo() { + Child c = new Child(); + Object o = c.bar(); + o.toString(); + } + + void bar() { + Object o1 = new Object(); + } + +} diff --git a/infer/tests/endtoend/BUCK b/infer/tests/endtoend/BUCK index c1a2615dc..22819e670 100644 --- a/infer/tests/endtoend/BUCK +++ b/infer/tests/endtoend/BUCK @@ -10,6 +10,7 @@ tests_dependencies = [ '//infer/tests/codetoanalyze/java/checkers:checkers', '//infer/tests/codetoanalyze/java/eradicate:eradicate', '//infer/tests/codetoanalyze/java/infer:infer', + '//infer/tests/codetoanalyze/java/incremental:incremental', '//infer/tests/codetoanalyze/java/tracing:tracing', ] @@ -97,6 +98,7 @@ java_test( '//infer/tests/endtoend/java/harness:harness', '//infer/tests/endtoend/java/tracing:tracing', '//infer/tests/endtoend/java/comparison:comparison', + '//infer/tests/endtoend/java/incremental:incremental', ], visibility=integration_tests, ) diff --git a/infer/tests/endtoend/java/incremental/BUCK b/infer/tests/endtoend/java/incremental/BUCK new file mode 100644 index 000000000..92b5c5cd4 --- /dev/null +++ b/infer/tests/endtoend/java/incremental/BUCK @@ -0,0 +1,18 @@ +java_test( + name='incremental', + 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/incremental/file_unchanged:analyze', + '//infer/tests/codetoanalyze/java/incremental/parent_changed:analyze', + '//infer/tests/codetoanalyze/java/incremental/child_changed:analyze', + ], + visibility=[ + 'PUBLIC', + ], +) diff --git a/infer/tests/endtoend/java/incremental/ChildChangedTest.java b/infer/tests/endtoend/java/incremental/ChildChangedTest.java new file mode 100644 index 000000000..a2b09d37d --- /dev/null +++ b/infer/tests/endtoend/java/incremental/ChildChangedTest.java @@ -0,0 +1,48 @@ +/* +* 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 endtoend.java.incremental; + +import static org.hamcrest.MatcherAssert.assertThat; +import static utils.matchers.NumberOfFilesAnalyzed.numberOfFilesAnalyzed; +import static utils.matchers.NumberOfProceduresAnalyzed.numberOfProceduresAnalyzed; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.io.*; + +import utils.InferException; +import utils.InferStats; + +public class ChildChangedTest { + + public static final String SOURCE_DIR = + "/infer/tests/codetoanalyze/java/incremental/child_changed/"; + + private static InferStats inferStats; + + @BeforeClass + public static void loadResults() throws InterruptedException, IOException { + inferStats = InferStats.loadInferStats(ChildChangedTest.class, SOURCE_DIR); + } + + @Test + public void unchangedFileNotReanalyzedInIncrementalMode() + throws IOException, InterruptedException, InferException { + assertThat( + "After changing the child file, parent and grandparent should be re-analyzed", + inferStats, + numberOfFilesAnalyzed(3)); + } + +} diff --git a/infer/tests/endtoend/java/incremental/FileUnchangedTest.java b/infer/tests/endtoend/java/incremental/FileUnchangedTest.java new file mode 100644 index 000000000..b5f98670c --- /dev/null +++ b/infer/tests/endtoend/java/incremental/FileUnchangedTest.java @@ -0,0 +1,57 @@ +/* +* 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 endtoend.java.incremental; + +import static org.hamcrest.MatcherAssert.assertThat; +import static utils.matchers.NumberOfFilesAnalyzed.numberOfFilesAnalyzed; +import static utils.matchers.NumberOfProceduresAnalyzed.numberOfProceduresAnalyzed; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.io.*; + +import utils.InferException; +import utils.InferStats; + +public class FileUnchangedTest { + + public static final String SOURCE_DIR = + "/infer/tests/codetoanalyze/java/incremental/file_unchanged/"; + + private static InferStats inferStats; + + @BeforeClass + public static void loadResults() throws InterruptedException, IOException { + inferStats = InferStats.loadInferStats(FileUnchangedTest.class, SOURCE_DIR); + } + + @Test + public void unchangedFileNotReanalyzedInIncrementalMode() + throws IOException, InterruptedException, InferException { + assertThat( + "Unchanged file should not be re-analyzed in incremental mode", + inferStats, + numberOfFilesAnalyzed(0)); + } + + @Test + public void unchangedProcdureNotReanalyzedInIncrementalMode() + throws IOException, InterruptedException, InferException { + assertThat( + "Unchanged procedure should not be re-analyzed in incremental mode", + inferStats, + numberOfProceduresAnalyzed(0)); + } + +} diff --git a/infer/tests/endtoend/java/incremental/ParentChangedTest.java b/infer/tests/endtoend/java/incremental/ParentChangedTest.java new file mode 100644 index 000000000..822ed4a07 --- /dev/null +++ b/infer/tests/endtoend/java/incremental/ParentChangedTest.java @@ -0,0 +1,61 @@ +/* +* 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 endtoend.java.incremental; + +import static org.hamcrest.MatcherAssert.assertThat; +import static utils.matchers.NumberOfFilesAnalyzed.numberOfFilesAnalyzed; +import static utils.matchers.NumberOfProceduresAnalyzed.numberOfProceduresAnalyzed; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.io.*; + +import utils.InferException; +import utils.InferStats; + +public class ParentChangedTest { + + public static final String SOURCE_DIR = + "/infer/tests/codetoanalyze/java/incremental/parent_changed/"; + + private static InferStats inferStats; + + @BeforeClass + public static void loadResults() throws InterruptedException, IOException { + inferStats = InferStats.loadInferStats(ParentChangedTest.class, SOURCE_DIR); + } + + @Test + public void unchangedFileNotReanalyzedInIncrementalMode() + throws IOException, InterruptedException, InferException { + assertThat( + "After changing only the parent file, the child file should not be re-analyzed", + inferStats, + numberOfFilesAnalyzed(1)); + assertThat( + "When adding a new procedure, the old ones should not be re-analyzed", + inferStats, + numberOfProceduresAnalyzed(1)); + } + + @Test + public void unchangedProcedureNotReanalyzedInIncrementalMode() + throws IOException, InterruptedException, InferException { + assertThat( + "When adding a new procedure, the old ones should not be re-analyzed", + inferStats, + numberOfProceduresAnalyzed(1)); + } + +} diff --git a/infer/tests/utils/InferStats.java b/infer/tests/utils/InferStats.java index 7583d6304..8b55a7ee8 100644 --- a/infer/tests/utils/InferStats.java +++ b/infer/tests/utils/InferStats.java @@ -22,6 +22,7 @@ import java.io.Reader; @JsonIgnoreProperties(ignoreUnknown=true) public class InferStats { + @JsonIgnoreProperties(ignoreUnknown=true) private static class IntFields { @JsonProperty(value = "files") int numFiles;