Bug 1479503: Check infer in ./mach static-analysis autotest. r=nalexander
☠☠ backed out by c5fbbf959e23 ☠ ☠
authorRobert Bartlensky <rbartlensky@mozilla.com>
Thu, 13 Sep 2018 20:58:03 +0000
changeset 492043 aae4f349fa588aa844cfb14fae278b776aed6cb7
parent 492042 f61e4114e9df9f39b2264267c9f4c7f616526ff5
child 492044 9b2e26f7005b5cdc27bdc08830ce39955b9cb197
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1479503
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1479503: Check infer in ./mach static-analysis autotest. r=nalexander Adds infer to ./mach static-analysis autotest. Differential Revision: https://phabricator.services.mozilla.com/D5692
.flake8
.hgignore
build/moz.configure/java.configure
build/moz.configure/java_common.configure
moz.configure
python/mozbuild/mozbuild/mach_commands.py
taskcluster/ci/docker-image/kind.yml
taskcluster/ci/static-analysis-autotest/kind.yml
taskcluster/ci/toolchain/linux.yml
taskcluster/docker/debian7-build/Dockerfile
taskcluster/docker/infer-build/Dockerfile
taskcluster/docker/static-analysis-build/Dockerfile
testing/mozharness/mozharness/base/script.py
testing/mozharness/mozharness/mozilla/building/buildbase.py
tools/infer/config.yaml
tools/infer/test/autotest/build.gradle
tools/infer/test/autotest/src/main/java/Biabduction.java
tools/infer/test/autotest/src/main/java/Biabduction.json
tools/infer/test/autotest/src/main/java/Checkers.java
tools/infer/test/autotest/src/main/java/Checkers.json
tools/infer/test/autotest/src/main/java/Eradicate.java
tools/infer/test/autotest/src/main/java/Racerd.java
tools/infer/test/autotest/src/main/java/Racerd.json
tools/infer/test/autotest/src/main/java/Starvation.java
tools/infer/test/autotest/src/main/java/Starvation.json
tools/infer/test/build.gradle
tools/infer/test/gradle.properties
tools/infer/test/gradle/wrapper/gradle-wrapper.jar
tools/infer/test/gradle/wrapper/gradle-wrapper.properties
tools/infer/test/gradlew
tools/infer/test/gradlew.bat
tools/infer/test/java.configure
tools/infer/test/moz.configure
tools/infer/test/settings.gradle
--- a/.flake8
+++ b/.flake8
@@ -17,8 +17,9 @@ exclude =
     js/*.configure,
     memory/moz.configure,
     mobile/android/*.configure,
     node_modules,
     security/nss/,
     testing/mochitest/pywebsocket,
     tools/lint/test/files,
     build/build-infer/build-infer.py,
+    tools/infer/test/*.configure,
--- a/.hgignore
+++ b/.hgignore
@@ -69,16 +69,17 @@ compile_commands\.json
 # Ignore the files and directory that JetBrains IDEs create.
 \.idea/
 \.iml$
 # Android Monitor in Android Studio creates a captures/ directory.
 ^captures/
 
 # Gradle cache.
 ^.gradle/
+^tools/infer/test/.gradle/
 
 # Local Gradle configuration properties.
 ^local.properties$
 
 # Python stuff installed at build time.
 ^third_party/python/psutil/.*\.so
 ^third_party/python/psutil/.*\.pyd
 ^third_party/python/psutil/build/
--- a/build/moz.configure/java.configure
+++ b/build/moz.configure/java.configure
@@ -1,61 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-
-# Java detection
-# ========================================================
-option('--with-java-bin-path', nargs=1,
-       help='Location of Java binaries (java, javac, jar)')
-
-
-@depends('--with-java-bin-path')
-@imports(_from='os', _import='environ')
-def java_search_paths(path):
-    if path:
-        # Look for javac and jar in the specified path.
-        return path
-    # With no path specified, look for javac and jar in $JAVA_HOME (if set)
-    # and $PATH.
-    if 'JAVA_HOME' in environ:
-        return [os.path.join(environ['JAVA_HOME'], 'bin'),
-                environ.get('PATH', '')]
-    return [environ.get('PATH')]
-
-# Finds the given java tool, failing with a custom error message if we can't
-# find it.
-
-
-@template
-def check_java_tool(tool):
-    check = check_prog(tool.upper(), (tool,), paths=java_search_paths,
-                       allow_missing=True)
-
-    @depends(check)
-    def require_tool(result):
-        if result is None:
-            die("The program %s was not found.  Set $JAVA_HOME to your Java "
-                "SDK directory or use '--with-java-bin-path={java-bin-dir}'"
-                % tool)
-        return result
-
-    return require_tool
-
-
-check_java_tool('java')
-check_java_tool('javah')
-check_java_tool('jar')
-check_java_tool('jarsigner')
-check_java_tool('keytool')
-javac = check_java_tool('javac')
-
+include('java_common.configure')
 
 @depends(javac)
 @checking('for javac version')
 @imports('subprocess')
 def javac_version(javac):
     try:
         output = subprocess.check_output([javac, '-version'],
                                          stderr=subprocess.STDOUT).rstrip()
new file mode 100644
--- /dev/null
+++ b/build/moz.configure/java_common.configure
@@ -0,0 +1,51 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Java detection
+# ========================================================
+option('--with-java-bin-path', nargs=1,
+       help='Location of Java binaries (java, javac, jar)')
+
+
+@depends('--with-java-bin-path')
+@imports(_from='os', _import='environ')
+def java_search_paths(path):
+    if path:
+        # Look for javac and jar in the specified path.
+        return path
+    # With no path specified, look for javac and jar in $JAVA_HOME (if set)
+    # and $PATH.
+    if 'JAVA_HOME' in environ:
+        return [os.path.join(environ['JAVA_HOME'], 'bin'),
+                environ.get('PATH', '')]
+    return [environ.get('PATH')]
+
+# Finds the given java tool, failing with a custom error message if we can't
+# find it.
+
+
+@template
+def check_java_tool(tool):
+    check = check_prog(tool.upper(), (tool,), paths=java_search_paths,
+                       allow_missing=True)
+
+    @depends(check)
+    def require_tool(result):
+        if result is None:
+            die("The program %s was not found.  Set $JAVA_HOME to your Java "
+                "SDK directory or use '--with-java-bin-path={java-bin-dir}'"
+                % tool)
+        return result
+
+    return require_tool
+
+
+check_java_tool('java')
+check_java_tool('javah')
+check_java_tool('jar')
+check_java_tool('jarsigner')
+check_java_tool('keytool')
+javac = check_java_tool('javac')
--- a/moz.configure
+++ b/moz.configure
@@ -562,16 +562,31 @@ def nsis_flags(host):
     if host.kernel != 'WINNT':
         return '-nocd'
     return ''
 
 set_config('MAKENSISU_FLAGS', nsis_flags)
 
 check_prog('7Z', ('7z', '7za'), allow_missing=True, when=target_is_windows)
 
+@depends(target, host, check_build_environment, '--help')
+@imports('os')
+def include_infer_autotest(target, host, build_env, help):
+    # Do not include autotest configuration on Windows or macos
+    # because infer is not available there
+    if target.kernel in ['Linux'] and host.kernel in ['Linux']:
+        path = os.path.join(build_env.topsrcdir, 'tools', 'infer', 'test', 'moz.configure')
+        # on some builds, this path won't exists, in which case we can just
+        # ignore the infer autotest
+        if os.path.exists(path):
+            return path
+    return None
+
+include(include_infer_autotest)
+
 # Fallthrough to autoconf-based configure
 include('build/moz.configure/old.configure')
 
 @depends(check_build_environment, build_project)
 @imports('__sandbox__')
 @imports('glob')
 def config_status_deps(build_env, build_project):
 
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -1675,24 +1675,18 @@ class StaticAnalysis(MachCommandBase):
             StaticAnalysisFooter,
             StaticAnalysisOutputManager,
         )
 
         self._set_log_level(verbose)
         self.log_manager.enable_all_structured_loggers()
 
         rc = self._build_compile_db(verbose=verbose)
-        if rc != 0:
-            return rc
-
-        rc = self._build_export(jobs=jobs, verbose=verbose)
-        if rc != 0:
-            return rc
-
-        rc = self._get_clang_tools(verbose=verbose)
+        rc = rc or self._build_export(jobs=jobs, verbose=verbose)
+        rc = rc or self._get_clang_tools(verbose=verbose)
         if rc != 0:
             return rc
 
         compile_db = json.loads(open(self._compile_db, 'r').read())
         total = 0
         import re
         name_re = re.compile('(' + ')|('.join(source) + ')')
         for f in compile_db:
@@ -1770,31 +1764,25 @@ class StaticAnalysis(MachCommandBase):
                      'This command is only available for linux64!')
             return rc
         # which checkers to use, and which folders to exclude
         all_checkers, third_party_path = self._get_infer_config()
         checkers, excludes = self._get_infer_args(
             checks=checks or all_checkers,
             third_party_path=third_party_path
         )
-        gradlew = mozpath.join(self.topsrcdir, 'gradlew')
+        rc = rc or self._gradle(['clean'])  # clean so that we can recompile
         # infer capture command
-        capture_cmd = [self._infer_path, 'capture'] + excludes + \
-            ['--', gradlew, task]
+        capture_cmd = [self._infer_path, 'capture'] + excludes + ['--']
+        rc = rc or self._gradle([task], infer_args=capture_cmd, verbose=verbose)
         tmp_file, args = self._get_infer_source_args(java_sources)
         # infer analyze command
         analysis_cmd = [self._infer_path, 'analyze', '--keep-going'] +  \
             checkers + args
-        # capture, then analyze the sources
-        for args in [[gradlew, 'clean'], capture_cmd, analysis_cmd]:
-            rc = self.run_process(args=args, cwd=self.topsrcdir,
-                                  pass_thru=True)
-            # if a command fails, break and close the tmp file before returning
-            if rc != 0:
-                break
+        rc = rc or self.run_process(args=analysis_cmd, cwd=self.topsrcdir, pass_thru=True)
         if tmp_file:
             tmp_file.close()
         return rc
 
     def _get_java_files(self, sources):
         java_sources = []
         for i in sources:
             f = mozpath.join(self.topsrcdir, i)
@@ -1871,89 +1859,94 @@ class StaticAnalysis(MachCommandBase):
         if fix:
             common_args += '-fix'
 
         return [
             self.virtualenv_manager.python_path, self._run_clang_tidy_path, '-j',
             str(jobs), '-p', self._compilation_commands_path
         ] + common_args + sources
 
+    def _gradle(self, args, infer_args=None, verbose=False, autotest=False,
+                suppress_output=True):
+        infer_args = infer_args or []
+        java_home = os.path.dirname(os.path.dirname(self.substs['JAVA']))
+        if autotest:
+            cwd = mozpath.join(self.topsrcdir, 'tools', 'infer', 'test')
+            gradle = mozpath.join(cwd, 'gradlew')
+        else:
+            gradle = self.substs['GRADLE']
+            cwd = self.topsrcdir
+        extra_env = {
+            'GRADLE_OPTS': '-Dfile.encoding=utf-8',  # see mobile/android/mach_commands.py
+            'JAVA_HOME': java_home,
+            'JAVA_TOOL_OPTIONS': '-Dfile.encoding=utf-8',
+        }
+        if suppress_output:
+            devnull = open(os.devnull, 'w')
+            return subprocess.call(
+                infer_args + [gradle] + args,
+                env=dict(os.environ, **extra_env),
+                cwd=cwd, stdout=devnull, stderr=subprocess.STDOUT, close_fds=True)
+        else:
+            return self.run_process(
+                infer_args + [gradle] + args,
+                append_env=extra_env,
+                pass_thru=True,  # Allow user to run gradle interactively.
+                ensure_exit_code=False,  # Don't throw on non-zero exit code.
+                cwd=cwd)
+
     @StaticAnalysisSubCommand('static-analysis', 'autotest',
                               'Run the auto-test suite in order to determine that'
                               ' the analysis did not regress.')
     @CommandArgument('--dump-results', '-d', default=False, action='store_true',
                      help='Generate the baseline for the regression test. Based on'
                      ' this baseline we will test future results.')
     @CommandArgument('--intree-tool', '-i', default=False, action='store_true',
                      help='Use a pre-aquired in-tree clang-tidy package.')
     @CommandArgument('checker_names', nargs='*', default=[],
                      help='Checkers that are going to be auto-tested.')
     def autotest(self, verbose=False, dump_results=False, intree_tool=False, checker_names=[]):
         # If 'dump_results' is True than we just want to generate the issues files for each
         # checker in particulat and thus 'force_download' becomes 'False' since we want to
         # do this on a local trusted clang-tidy package.
         self._set_log_level(verbose)
         self._dump_results = dump_results
-
-        force_download = True
-
-        if self._dump_results:
-            force_download = False
+        force_download = not self._dump_results
 
         # Function return codes
         self.TOOLS_SUCCESS = 0
         self.TOOLS_FAILED_DOWNLOAD = 1
         self.TOOLS_UNSUPORTED_PLATFORM = 2
         self.TOOLS_CHECKER_NO_TEST_FILE = 3
         self.TOOLS_CHECKER_RETURNED_NO_ISSUES = 4
         self.TOOLS_CHECKER_RESULT_FILE_NOT_FOUND = 5
         self.TOOLS_CHECKER_DIFF_FAILED = 6
         self.TOOLS_CHECKER_NOT_FOUND = 7
         self.TOOLS_CHECKER_FAILED_FILE = 8
-
-        # Configure the tree or download clang-tidy package, depending on the option that we choose
-        if intree_tool:
-            _, config, _ = self._get_config_environment()
-            clang_tools_path = self.topsrcdir
-            self._clang_tidy_path = mozpath.join(
-                clang_tools_path, "clang", "bin",
-                "clang-tidy" + config.substs.get('BIN_SUFFIX', ''))
-            self._clang_format_path = mozpath.join(
-                clang_tools_path, "clang", "bin",
-                "clang-format" + config.substs.get('BIN_SUFFIX', ''))
-            self._clang_apply_replacements = mozpath.join(
-                clang_tools_path, "clang", "bin",
-                "clang-apply-replacements" + config.substs.get('BIN_SUFFIX', ''))
-            self._run_clang_tidy_path = mozpath.join(clang_tools_path, "clang", "share",
-                                                     "clang", "run-clang-tidy.py")
-            self._clang_format_diff = mozpath.join(clang_tools_path, "clang", "share",
-                                                   "clang", "clang-format-diff.py")
-
-            # Ensure that clang-tidy is present
-            rc = not os.path.exists(self._clang_tidy_path)
-        else:
-            rc = self._get_clang_tools(force=force_download, verbose=verbose)
-
+        self.TOOLS_GRADLE_FAILED = 9
+
+        rc = self._get_clang_tools(force=force_download, verbose=verbose, intree_tool=intree_tool)
         if rc != 0:
             self.log(logging.ERROR, 'ERROR: static-analysis', {},
                      'clang-tidy unable to locate package.')
             return self.TOOLS_FAILED_DOWNLOAD
 
         self._clang_tidy_base_path = mozpath.join(self.topsrcdir, "tools", "clang-tidy")
 
         # For each checker run it
         f = open(mozpath.join(self._clang_tidy_base_path, "config.yaml"))
         import yaml
         config = yaml.safe_load(f)
         platform, _ = self.platform
 
         if platform not in config['platforms']:
             self.log(logging.ERROR, 'static-analysis', {},
-                     "RUNNING: clang-tidy autotest for platform {} not supported.".format(platform))
-            return TOOLS_UNSUPORTED_PLATFORM
+                     "RUNNING: clang-tidy autotest for platform {} not supported."
+                     .format(platform))
+            return self.TOOLS_UNSUPORTED_PLATFORM
 
         import concurrent.futures
         import multiprocessing
         import shutil
 
         max_workers = multiprocessing.cpu_count()
 
         self.log(logging.INFO, 'static-analysis', {},
@@ -2004,38 +1997,158 @@ class StaticAnalysis(MachCommandBase):
                 self.log(logging.INFO, 'static-analysis', {}, "FAIL: clang-tidy some tests failed.")
                 # Also delete the tmp folder
                 shutil.rmtree(self._compilation_commands_path)
                 return error_code
 
         self.log(logging.INFO, 'static-analysis', {}, "SUCCESS: clang-tidy all tests passed.")
         # Also delete the tmp folder
         shutil.rmtree(self._compilation_commands_path)
-        return self.TOOLS_SUCCESS
+        return self._autotest_infer(intree_tool, force_download, verbose)
 
     def _create_temp_compilation_db(self, config):
         directory = tempfile.mkdtemp(prefix='cc')
         with open(mozpath.join(directory, "compile_commands.json"), "wb") as file_handler:
             compile_commands = []
             director = mozpath.join(self.topsrcdir, 'tools', 'clang-tidy', 'test')
             for item in config['clang_checkers']:
                 if item['name'] in ['-*', 'mozilla-*']:
                     continue
                 file = item['name'] + '.cpp'
                 element = {}
                 element["directory"] = director
-                element["command"] = 'cpp '+ file
+                element["command"] = 'cpp ' + file
                 element["file"] = mozpath.join(director, file)
                 compile_commands.append(element)
 
             json.dump(compile_commands, file_handler)
             file_handler.flush()
 
             return directory
 
+    def _autotest_infer(self, intree_tool, force_download, verbose):
+        # infer is not available on other platforms, but autotest should work even without
+        # it being installed
+        if self.platform[0] == 'linux64':
+            rc = self._get_infer(force=force_download, verbose=verbose, intree_tool=intree_tool)
+            if rc != 0:
+                self.log(logging.ERROR, 'ERROR: static-analysis', {},
+                         'infer unable to locate package.')
+                return self.TOOLS_FAILED_DOWNLOAD
+            self.__infer_tool = mozpath.join(self.topsrcdir, 'tools', 'infer')
+            self.__infer_test_folder = mozpath.join(self.__infer_tool, 'test')
+
+            import concurrent.futures
+            import multiprocessing
+            max_workers = multiprocessing.cpu_count()
+            self.log(logging.INFO, 'static-analysis', {},
+                     "RUNNING: infer autotest for platform {0} with {1} workers.".format(
+                         self.platform[0], max_workers))
+            # clean previous autotest if it exists
+            rc = self._gradle(['autotest:clean'], autotest=True)
+            if rc != 0:
+                return rc
+            import yaml
+            with open(mozpath.join(self.__infer_tool, 'config.yaml')) as f:
+                config = yaml.safe_load(f)
+            with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
+                futures = []
+                for item in config['infer_checkers']:
+                    if item['publish']:
+                        futures.append(executor.submit(self._verify_infer_checker, item))
+                # this is always included in check-java, but not in config.yaml
+                futures.append(executor.submit(self._verify_infer_checker,
+                                               {'name': 'checkers'}))
+                for future in concurrent.futures.as_completed(futures):
+                    ret_val = future.result()
+                    if ret_val != self.TOOLS_SUCCESS:
+                        return ret_val
+            self.log(logging.INFO, 'static-analysis', {}, "SUCCESS: infer all tests passed.")
+        else:
+            self.log(logging.WARNING, 'static-analysis', {},
+                     "Skipping infer autotest, because it is only available on linux64!")
+        return self.TOOLS_SUCCESS
+
+    def _verify_infer_checker(self, item):
+        '''Given a checker, this method verifies the following:
+          1. if there is a `checker`.json and `checker`.java file in
+             `tools/infer/test/autotest/src`
+          2. if running infer on `checker`.java yields the same result as `checker`.json
+        An `item` is simply a dictionary, which needs to have a `name` field set, which is the
+        name of the checker.
+        '''
+        def to_camelcase(str):
+            return ''.join([s.capitalize() for s in str.split('-')])
+        check = item['name']
+        test_file_path = mozpath.join(self.__infer_tool, 'test', 'autotest', 'src',
+                                      'main', 'java', to_camelcase(check))
+        test_file_path_java = test_file_path + '.java'
+        test_file_path_json = test_file_path + '.json'
+        self.log(logging.INFO, 'static-analysis', {}, "RUNNING: infer check {}.".format(check))
+        # Verify if the test file exists for this checker
+        if not os.path.exists(test_file_path_java):
+            self.log(logging.ERROR, 'static-analysis', {},
+                     "ERROR: infer check {} doesn't have a test file.".format(check))
+            return self.TOOLS_CHECKER_NO_TEST_FILE
+        # run infer on a particular test file
+        out_folder = mozpath.join(self.__infer_test_folder, 'test-infer-{}'.format(check))
+        if check == 'checkers':
+            check_arg = ['-a', 'checkers']
+        else:
+            check_arg = ['--{}-only'.format(check)]
+        infer_args = [self._infer_path, 'run'] + check_arg + ['-o', out_folder, '--']
+        gradle_args = ['autotest:compileInferTest{}'.format(to_camelcase(check))]
+        rc = self._gradle(gradle_args, infer_args=infer_args, autotest=True)
+        if rc != 0:
+            self.log(logging.ERROR, 'static-analysis', {},
+                     "ERROR: infer failed to execute gradle {}.".format(gradle_args))
+            return self.TOOLS_GRADLE_FAILED
+        issues = json.load(open(mozpath.join(out_folder, 'report.json')))
+        # remove folder that infer creates because the issues are loaded into memory
+        import shutil
+        shutil.rmtree(out_folder)
+        # Verify to see if we got any issues, if not raise exception
+        if not issues:
+            self.log(
+                logging.ERROR, 'static-analysis', {},
+                "ERROR: infer check {0} did not find any issues in its associated test suite."
+                .format(check)
+            )
+            return self.TOOLS_CHECKER_RETURNED_NO_ISSUES
+        if self._dump_results:
+            self._build_autotest_result(test_file_path_json, issues)
+        else:
+            if not os.path.exists(test_file_path_json):
+                # Result file for test not found maybe regenerate it?
+                self.log(
+                    logging.ERROR, 'static-analysis', {},
+                    "ERROR: infer result file not found for check {0}".format(check)
+                )
+                return self.TOOLS_CHECKER_RESULT_FILE_NOT_FOUND
+            # Read the pre-determined issues
+            baseline_issues = self._get_autotest_stored_issues(test_file_path_json)
+
+            def ordered(obj):
+                if isinstance(obj, dict):
+                    return sorted((k, ordered(v)) for k, v in obj.items())
+                if isinstance(obj, list):
+                    return sorted(ordered(x) for x in obj)
+                return obj
+            # Compare the two lists
+            if ordered(issues) != ordered(baseline_issues):
+                error_str = "ERROR: in check {} Expected: ".format(check)
+                error_str += '\n' + json.dumps(baseline_issues, indent=2)
+                error_str += '\n Got:\n' + json.dumps(issues, indent=2)
+                self.log(logging.ERROR, 'static-analysis', {},
+                         'ERROR: infer autotest for check {} failed, check stdout for more details'
+                         .format(check))
+                print(error_str)
+                return self.TOOLS_CHECKER_DIFF_FAILED
+        return self.TOOLS_SUCCESS
+
     @StaticAnalysisSubCommand('static-analysis', 'install',
                               'Install the static analysis helper tool')
     @CommandArgument('source', nargs='?', type=str,
                      help='Where to fetch a local archive containing the static-analysis and '
                      'format helper tool.'
                           'It will be installed in ~/.mozbuild/clang-tools and ~/.mozbuild/infer.'
                           'Can be omitted, in which case the latest clang-tools and infer '
                           'helper for the platform would be automatically detected and installed.')
@@ -2284,36 +2397,39 @@ class StaticAnalysis(MachCommandBase):
         # Converts all the paths to absolute pathnames
         tmp_path = []
         for f in paths:
             tmp_path.append(os.path.abspath(f))
         return tmp_path
 
     def _get_clang_tools(self, force=False, skip_cache=False,
                          source=None, download_if_needed=True,
-                         verbose=False):
+                         verbose=False, intree_tool=False):
         rc, config, _ = self._get_config_environment()
 
         if rc != 0:
             return rc
 
-        clang_tools_path = mozpath.join(self._mach_context.state_dir, "clang-tools")
+        clang_tools_path = self.topsrcdir if intree_tool else \
+            mozpath.join(self._mach_context.state_dir, "clang-tools")
         self._clang_tidy_path = mozpath.join(clang_tools_path, "clang", "bin",
                                              "clang-tidy" + config.substs.get('BIN_SUFFIX', ''))
         self._clang_format_path = mozpath.join(
             clang_tools_path, "clang", "bin",
             "clang-format" + config.substs.get('BIN_SUFFIX', ''))
         self._clang_apply_replacements = mozpath.join(
             clang_tools_path, "clang", "bin",
             "clang-apply-replacements" + config.substs.get('BIN_SUFFIX', ''))
         self._run_clang_tidy_path = mozpath.join(clang_tools_path, "clang", "share", "clang",
                                                  "run-clang-tidy.py")
         self._clang_format_diff = mozpath.join(clang_tools_path, "clang", "share", "clang",
                                                "clang-format-diff.py")
-
+        if intree_tool:
+            # Ensure that clang-tidy is present
+            return not os.path.exists(self._clang_tidy_path)
         if os.path.exists(self._clang_tidy_path) and \
            os.path.exists(self._clang_format_path) and \
            os.path.exists(self._clang_apply_replacements) and \
            os.path.exists(self._run_clang_tidy_path) and \
            not force:
             return 0
         else:
             if os.path.isdir(clang_tools_path) and download_if_needed:
@@ -2404,25 +2520,27 @@ class StaticAnalysis(MachCommandBase):
                         continue  # empty or comment
                     magics = ['exclude']
                     if pattern.startswith('^'):
                         magics += ['top']
                         pattern = pattern[1:]
                     args += [':({0}){1}'.format(','.join(magics), pattern)]
         return args
 
-    def _get_infer(self, force=False, skip_cache=False,
-                   download_if_needed=True, verbose=False):
+    def _get_infer(self, force=False, skip_cache=False, download_if_needed=True,
+                   verbose=False, intree_tool=False):
         rc, config, _ = self._get_config_environment()
         if rc != 0:
             return rc
-        infer_path = mozpath.join(self._mach_context.state_dir, 'infer')
-        self._infer_path = mozpath.join(infer_path, 'infer', 'bin',
-                                        'infer' +
+        infer_path = self.topsrcdir if intree_tool else \
+            mozpath.join(self._mach_context.state_dir, 'infer')
+        self._infer_path = mozpath.join(infer_path, 'infer', 'bin', 'infer' +
                                         config.substs.get('BIN_SUFFIX', ''))
+        if intree_tool:
+            return not os.path.exists(self._infer_path)
         if os.path.exists(self._infer_path) and not force:
             return 0
         else:
             if os.path.isdir(infer_path) and download_if_needed:
                 # The directory exists, perhaps it's corrupted?  Delete it
                 # and start from scratch.
                 import shutil
                 shutil.rmtree(infer_path)
--- a/taskcluster/ci/docker-image/kind.yml
+++ b/taskcluster/ci/docker-image/kind.yml
@@ -81,19 +81,19 @@ jobs:
       - deb9-mercurial
       - deb9-python-zstandard
   android-build:
     symbol: I(agb)
     parent: debian9-base
   fetch:
     symbol: I(fetch)
     parent: debian9-base
-  infer-build:
-    symbol: I(infer)
-    parent: debian9-base
+  static-analysis-build:
+    symbol: I(static-analysis-build)
+    parent: android-build
   mingw32-build:
     symbol: I(mingw)
     parent: debian9-base
   index-task:
     symbol: I(idx)
   funsize-update-generator:
     symbol: I(pg)
   google-play-strings:
--- a/taskcluster/ci/static-analysis-autotest/kind.yml
+++ b/taskcluster/ci/static-analysis-autotest/kind.yml
@@ -31,16 +31,20 @@ job-defaults:
         kind: build
         tier: 1
 
 jobs:
     linux64-st-autotest/debug:
         description: "Linux64 Debug Static Analysis Autotest"
         index:
             job-name: linux64-st-autotest-debug
+        worker:
+            docker-image: {in-tree: static-analysis-build}
+            env:
+                PERFHERDER_EXTRA_OPTIONS: static-analysis-autotest
         treeherder:
             platform: linux64/debug
         worker-type: aws-provisioner-v1/gecko-t-linux-large
         run:
             config:
                 - builds/releng_base_firefox.py
                 - builds/releng_sub_linux_configs/64_stat_and_debug.py
             tooltool-downloads: public
--- a/taskcluster/ci/toolchain/linux.yml
+++ b/taskcluster/ci/toolchain/linux.yml
@@ -153,17 +153,17 @@ linux64-infer:
         job-name: linux64-infer
     treeherder:
         kind: build
         platform: toolchains/opt
         symbol: TL(infer)
         tier: 1
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
-        docker-image: {in-tree: infer-build}
+        docker-image: {in-tree: static-analysis-build}
         max-run-time: 3600
     run:
         using: toolchain-script
         script: build-infer-linux.sh
         resources:
             - 'build/build-infer/build-infer.py'
             - 'build/build-infer/infer-linux64.json'
         toolchain-artifact: public/build/infer.tar.xz
--- a/taskcluster/docker/debian7-build/Dockerfile
+++ b/taskcluster/docker/debian7-build/Dockerfile
@@ -22,16 +22,17 @@ RUN apt-get update && \
       autoconf2.13 \
       automake \
       bzip2 \
       curl \
       file \
       gawk \
       gcc-multilib \
       gnupg \
+      openjdk-7-jdk \
       p7zip-full \
       procps \
       python-pip \
       python-setuptools \
       python-virtualenv \
       rsync \
       screen \
       tar \
rename from taskcluster/docker/infer-build/Dockerfile
rename to taskcluster/docker/static-analysis-build/Dockerfile
--- a/taskcluster/docker/infer-build/Dockerfile
+++ b/taskcluster/docker/static-analysis-build/Dockerfile
@@ -5,26 +5,54 @@ MAINTAINER Robert Bartlensky <rbartlensk
 VOLUME /builds/worker/checkouts
 VOLUME /builds/worker/workspace
 VOLUME /builds/worker/tooltool-cache
 
 ENV XZ_OPT=-T0
 
 RUN apt-get update && \
     apt-get install \
-      autoconf \
+      autoconf2.13 \
+      automake \
       bison \
       bzip2 \
+      cmake \
       flex \
       curl \
-      git \
       opam \
       libsqlite3-dev \
-      autoconf \
-      automake \
-      cmake \
+      file \
+      gawk \
+      gcc-multilib \
+      gnupg \
       libc6-dev \
       openjdk-8-jdk-headless \
       pkg-config \
       patch \
+      p7zip-full \
+      procps \
+      python-pip \
+      python-setuptools \
+      python-virtualenv \
+      rsync \
+      screen \
       tar \
       unzip \
-      zlib1g-dev
+      uuid \
+      valgrind \
+      wget \
+      yasm \
+      zip \
+      zlib1g-dev \
+      x11-utils \
+      xvfb \
+      linux-libc-dev \
+      libdbus-glib-1-dev \
+      libfontconfig1-dev \
+      libfreetype6-dev \
+      libgconf2-dev \
+      libgtk-3-dev \
+      libgtk2.0-dev \
+      libpango1.0-dev \
+      libpulse-dev \
+      libx11-xcb-dev \
+      libxt-dev \
+      lib32z1
--- a/testing/mozharness/mozharness/base/script.py
+++ b/testing/mozharness/mozharness/base/script.py
@@ -1,9 +1,8 @@
-
 #!/usr/bin/env python
 # ***** BEGIN LICENSE BLOCK *****
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 # ***** END LICENSE BLOCK *****
 """Generic script objects.
 
--- a/testing/mozharness/mozharness/mozilla/building/buildbase.py
+++ b/testing/mozharness/mozharness/mozilla/building/buildbase.py
@@ -1221,42 +1221,52 @@ or run without that action (ie: --no-{ac
         self._run_mach_command_in_build_env(['build', '-v'])
 
         self.generate_build_props(console_output=True, halt_on_failure=True)
         self._generate_build_stats()
 
     def static_analysis_autotest(self):
         """Run mach static-analysis autotest, in order to make sure we dont regress"""
         self.preflight_build()
-        self._run_mach_command_in_build_env(['static-analysis', 'autotest', '--intree-tool'])
+        self._run_mach_command_in_build_env(['configure'])
+        self._run_mach_command_in_build_env(['static-analysis', 'autotest',
+                                             '--intree-tool'],
+                                            use_subprocess=True)
 
-    def _run_mach_command_in_build_env(self, args):
+    def _run_mach_command_in_build_env(self, args, use_subprocess=False):
         """Run a mach command in a build context."""
         env = self.query_build_env()
         env.update(self.query_mach_build_env())
-
         dirs = self.query_abs_dirs()
 
         if 'MOZILLABUILD' in os.environ:
             # We found many issues with intermittent build failures when not invoking mach via bash.
             # See bug 1364651 before considering changing.
             mach = [
                 os.path.join(os.environ['MOZILLABUILD'], 'msys', 'bin', 'bash.exe'),
                 os.path.join(dirs['abs_src_dir'], 'mach')
             ]
         else:
             mach = [sys.executable, 'mach']
 
-        return_code = self.run_command(
-            command=mach + ['--log-no-times'] + args,
-            cwd=dirs['abs_src_dir'],
-            env=env,
-            output_timeout=self.config.get('max_build_output_timeout', 60 * 40)
-        )
-
+        # XXX See bug 1483883
+        # Work around an interaction between Gradle and mozharness
+        # Not using `subprocess` causes gradle to hang
+        if use_subprocess:
+            import subprocess
+            return_code = subprocess.call(mach + ['--log-no-times'] + args,
+                                          env=env, cwd=dirs['abs_src_dir'])
+        else:
+            return_code = self.run_command(
+                command=mach + ['--log-no-times'] + args,
+                cwd=dirs['abs_src_dir'],
+                env=env,
+                output_timeout=self.config.get('max_build_output_timeout',
+                                               60 * 40)
+            )
         if return_code:
             self.return_code = self.worst_level(
                 EXIT_STATUS_DICT[TBPL_FAILURE], self.return_code,
                 AUTOMATION_EXIT_CODES[::-1]
             )
             self.fatal("'mach %s' did not run successfully. Please check "
                        "log for errors." % ' '.join(args))
 
--- a/tools/infer/config.yaml
+++ b/tools/infer/config.yaml
@@ -1,23 +1,31 @@
 ---
 target: obj-x86_64-pc-linux-gnu
 # It is used by 'mach static-analysis' and 'mozreview static-analysis bot'
 # in order to have consistency across the used checkers.
 platforms:
   - linux64
 infer_checkers:
+  # no issues were ever trigger by this
   - name: check-nullable
+    publish: !!bool no
+  - name: biabduction
     publish: !!bool yes
+  # very very noisy
+  # it could be useful, but it won't be part of the default enabled checkers
   - name: eradicate
     publish: !!bool no
+  # hard to use, not useful
   - name: quandary
-    publish: !!bool yes
+    publish: !!bool no
   - name: starvation
     publish: !!bool yes
+  # experimental
   - name: litho
-    publish: !!bool yes
+    publish: !!bool no
   - name: racerd
     publish: !!bool yes
+  # I think this is only for c++, can't trigger these errors in Java
   - name: liveness
-    publish: !!bool yes
+    publish: !!bool no
 # Third party files from mozilla-central
 third_party: tools/rewriting/ThirdPartyPaths.txt
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/autotest/build.gradle
@@ -0,0 +1,23 @@
+apply plugin: 'java'
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    compile "com.google.code.findbugs:jsr305:3.0.2"
+}
+
+def createSingleTask = { name ->
+    task("compileInferTest${name}", type: JavaCompile) {
+        source = fileTree(dir: '.', include: "src/main/java/${name}.java")
+        classpath = project.configurations.compileClasspath
+        destinationDir = file("${topobjdir}/gradle/build/tools/infer/test/autotest")
+    }
+}
+
+createSingleTask('Biabduction')
+createSingleTask('Checkers')
+createSingleTask('Eradicate')
+createSingleTask('Racerd')
+createSingleTask('Starvation')
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/autotest/src/main/java/Biabduction.java
@@ -0,0 +1,22 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import javax.annotation.Nullable;
+import java.util.List;
+
+public class Biabduction {
+    private String get() { return null; }
+
+    public void f1() {
+        get().length(); // error
+    }
+
+    public void f2() {
+        try {
+            get().length(); // error
+        } catch (NullPointerException e) {
+
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/autotest/src/main/java/Biabduction.json
@@ -0,0 +1,114 @@
+[
+    {
+        "bug_class": "PROVER",
+        "bug_trace": [
+            {
+                "column_number": -1,
+                "description": "start of procedure f1()",
+                "filename": "autotest/src/main/java/Biabduction.java",
+                "level": 0,
+                "line_number": 11
+            },
+            {
+                "column_number": -1,
+                "description": "",
+                "filename": "autotest/src/main/java/Biabduction.java",
+                "level": 0,
+                "line_number": 12
+            },
+            {
+                "column_number": -1,
+                "description": "start of procedure get()",
+                "filename": "autotest/src/main/java/Biabduction.java",
+                "level": 1,
+                "line_number": 9
+            },
+            {
+                "column_number": -1,
+                "description": "return from a call to String Biabduction.get()",
+                "filename": "autotest/src/main/java/Biabduction.java",
+                "level": 1,
+                "line_number": 9
+            },
+            {
+                "column_number": -1,
+                "description": "",
+                "filename": "autotest/src/main/java/Biabduction.java",
+                "level": 0,
+                "line_number": 12
+            }
+        ],
+        "bug_type": "NULL_DEREFERENCE",
+        "bug_type_hum": "Null Dereference",
+        "censored_reason": "",
+        "column": -1,
+        "file": "autotest/src/main/java/Biabduction.java",
+        "hash": "918d7eaedf45f651f04c55554c72478c",
+        "key": "Biabduction.java|f1|NULL_DEREFERENCE",
+        "kind": "ERROR",
+        "line": 12,
+        "node_key": "9afcdcc9d4253c36267a0d34b98c337d",
+        "procedure": "void Biabduction.f1()",
+        "procedure_id": "Biabduction.f1():void.4b49520e7621606a0d5661886ff0b098",
+        "procedure_start_line": 11,
+        "qualifier": "object returned by `get(this)` could be null and is dereferenced at line 12.",
+        "severity": "HIGH",
+        "visibility": "user"
+    },
+    {
+        "bug_class": "PROVER",
+        "bug_trace": [
+            {
+                "column_number": -1,
+                "description": "start of procedure f2()",
+                "filename": "autotest/src/main/java/Biabduction.java",
+                "level": 0,
+                "line_number": 15
+            },
+            {
+                "column_number": -1,
+                "description": "",
+                "filename": "autotest/src/main/java/Biabduction.java",
+                "level": 0,
+                "line_number": 17
+            },
+            {
+                "column_number": -1,
+                "description": "start of procedure get()",
+                "filename": "autotest/src/main/java/Biabduction.java",
+                "level": 1,
+                "line_number": 9
+            },
+            {
+                "column_number": -1,
+                "description": "return from a call to String Biabduction.get()",
+                "filename": "autotest/src/main/java/Biabduction.java",
+                "level": 1,
+                "line_number": 9
+            },
+            {
+                "column_number": -1,
+                "description": "",
+                "filename": "autotest/src/main/java/Biabduction.java",
+                "level": 0,
+                "line_number": 17
+            }
+        ],
+        "bug_type": "NULL_DEREFERENCE",
+        "bug_type_hum": "Null Dereference",
+        "censored_reason": "",
+        "column": -1,
+        "file": "autotest/src/main/java/Biabduction.java",
+        "hash": "bc952ce8bad58dac5cb6672dc3150524",
+        "key": "Biabduction.java|f2|NULL_DEREFERENCE",
+        "kind": "ERROR",
+        "line": 17,
+        "node_key": "9afcdcc9d4253c36267a0d34b98c337d",
+        "procedure": "void Biabduction.f2()",
+        "procedure_id": "Biabduction.f2():void.41c05a632eb912a458482c1e2e4dcbb4",
+        "procedure_start_line": 15,
+        "qualifier": "object returned by `get(this)` could be null and is dereferenced at line 17.",
+        "severity": "HIGH",
+        "visibility": "user"
+    }
+]
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/autotest/src/main/java/Checkers.java
@@ -0,0 +1,34 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+
+public class Checkers {
+    public static void leak() {
+        try {
+            BufferedReader br = new BufferedReader(
+                new FileReader(new File("some.txt"))
+            );
+        } catch (Exception e) {
+
+        }
+    }
+
+    public static void error1() {
+        String str = null;
+        try {
+            int x = str.length(); // Error: even if exception is caught
+        } catch (NullPointerException e) {
+
+        }
+    }
+
+    public static void error2() {
+        String str = null;
+        int x = str.length(); // Error: not checking for null
+    }
+
+}
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/autotest/src/main/java/Checkers.json
@@ -0,0 +1,121 @@
+[
+    {
+        "bug_class": "PROVER",
+        "bug_trace": [
+            {
+                "column_number": -1,
+                "description": "start of procedure leak()",
+                "filename": "autotest/src/main/java/Checkers.java",
+                "level": 0,
+                "line_number": 10
+            },
+            {
+                "column_number": -1,
+                "description": "",
+                "filename": "autotest/src/main/java/Checkers.java",
+                "level": 0,
+                "line_number": 12
+            }
+        ],
+        "bug_type": "RESOURCE_LEAK",
+        "bug_type_hum": "Resource Leak",
+        "censored_reason": "",
+        "column": -1,
+        "file": "autotest/src/main/java/Checkers.java",
+        "hash": "56806153823413731f2e2166ed8d30a0",
+        "key": "Checkers.java|leak|RESOURCE_LEAK",
+        "kind": "ERROR",
+        "line": 12,
+        "node_key": "3a2af627d5d1f10e1994f6259cf18e4c",
+        "procedure": "void Checkers.leak()",
+        "procedure_id": "Checkers.leak():void.e21648e10d3037f4559cdb7c08642c84",
+        "procedure_start_line": 10,
+        "qualifier": "resource of type `java.io.FileReader` acquired by call to `new()` at line 12 is not released after line 12.",
+        "severity": "HIGH",
+        "visibility": "user"
+    },
+    {
+        "bug_class": "PROVER",
+        "bug_trace": [
+            {
+                "column_number": -1,
+                "description": "start of procedure error1()",
+                "filename": "autotest/src/main/java/Checkers.java",
+                "level": 0,
+                "line_number": 20
+            },
+            {
+                "column_number": -1,
+                "description": "",
+                "filename": "autotest/src/main/java/Checkers.java",
+                "level": 0,
+                "line_number": 21
+            },
+            {
+                "column_number": -1,
+                "description": "",
+                "filename": "autotest/src/main/java/Checkers.java",
+                "level": 0,
+                "line_number": 23
+            }
+        ],
+        "bug_type": "NULL_DEREFERENCE",
+        "bug_type_hum": "Null Dereference",
+        "censored_reason": "",
+        "column": -1,
+        "file": "autotest/src/main/java/Checkers.java",
+        "hash": "6de26e7c66c71b1114ad233679d55640",
+        "key": "Checkers.java|error1|NULL_DEREFERENCE",
+        "kind": "ERROR",
+        "line": 23,
+        "node_key": "c281f77c6dae544ee5fb7d5e2bb35118",
+        "procedure": "void Checkers.error1()",
+        "procedure_id": "Checkers.error1():void.59417424d80960700a32012973e98db5",
+        "procedure_start_line": 20,
+        "qualifier": "object `str` last assigned on line 21 could be null and is dereferenced at line 23.",
+        "severity": "HIGH",
+        "visibility": "user"
+    },
+    {
+        "bug_class": "PROVER",
+        "bug_trace": [
+            {
+                "column_number": -1,
+                "description": "start of procedure error2()",
+                "filename": "autotest/src/main/java/Checkers.java",
+                "level": 0,
+                "line_number": 29
+            },
+            {
+                "column_number": -1,
+                "description": "",
+                "filename": "autotest/src/main/java/Checkers.java",
+                "level": 0,
+                "line_number": 30
+            },
+            {
+                "column_number": -1,
+                "description": "",
+                "filename": "autotest/src/main/java/Checkers.java",
+                "level": 0,
+                "line_number": 31
+            }
+        ],
+        "bug_type": "NULL_DEREFERENCE",
+        "bug_type_hum": "Null Dereference",
+        "censored_reason": "",
+        "column": -1,
+        "file": "autotest/src/main/java/Checkers.java",
+        "hash": "39e021b634ab428af7be2034688491a7",
+        "key": "Checkers.java|error2|NULL_DEREFERENCE",
+        "kind": "ERROR",
+        "line": 31,
+        "node_key": "c281f77c6dae544ee5fb7d5e2bb35118",
+        "procedure": "void Checkers.error2()",
+        "procedure_id": "Checkers.error2():void.e9146d80ba20c908c11d08947cd89d06",
+        "procedure_start_line": 29,
+        "qualifier": "object `str` last assigned on line 30 could be null and is dereferenced at line 31.",
+        "severity": "HIGH",
+        "visibility": "user"
+    }
+]
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/autotest/src/main/java/Eradicate.java
@@ -0,0 +1,57 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import javax.annotation.Nullable;
+
+// Examples taken from the infer website.
+public class Eradicate {
+
+    public String f; // Because it is not annoted with nullable -> can never be null!
+
+    public void field(@Nullable Eradicate x) {
+        x.f = "3"; // Error: Eradicate null field access
+    }
+
+    public void method(@Nullable Object x) {
+        String s = x.toString(); // Error: Eradicate null method call
+    }
+
+    public void filedNotNull(@Nullable String s) {
+        f = s; // Error: Eradicate field not nullable
+    }
+
+    public Eradicate() {} // Error: Eradicate field not initialized
+
+    public void str(Eradicate x) {
+        String s = x.toString();
+    }
+
+    public void callStr(@Nullable Eradicate x) {
+        str(x); // Error:  Eradicate parameter not nullable
+    }
+
+    public String shouldNotReturnNullBecauseNotAnnotated() {
+        return null; // Error: Eradicate return not nullable
+    }
+
+    public void redundant() {
+        String s = new String("abc");
+        if (s != null) { // Error: Eradicate condition redundant
+            int n = s.length();
+        }
+    }
+
+    @Nullable
+    public static String someMethod() {
+        return ""; // Error: Eradicate return overannotated
+    }
+}
+
+class B extends Eradicate {
+    @Nullable public String shouldNotReturnNullBecauseNotAnnotated() {
+        return null; // Error: Eradicate inconsistent subclass return annotation
+    }
+
+    public void field(Eradicate x) {} // Error: Inconsistent subclass parameter annotation
+}
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/autotest/src/main/java/Racerd.java
@@ -0,0 +1,40 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import javax.annotation.concurrent.ThreadSafe;
+
+// Examples taken from the infer website.
+@ThreadSafe
+public class Racerd {
+    private int mTemperature;
+
+    public void makeDinner() {
+        boilWater();
+    }
+
+    private void boilWater() {
+        mTemperature = 100; //Error: unprotected write.
+    }
+}
+
+@ThreadSafe
+class Account {
+
+    int mBalance = 0;
+
+    public void deposit(int amount) {
+        if (amount > 0) {
+            mBalance += amount; // Error: unsynchronized write
+        }
+    }
+
+    public int withdraw(int amount){
+        if (amount >= 0 && mBalance - amount >= 0) {
+            mBalance -= amount; // Error: unsynchronized write
+            return mBalance; // Error: unsynchronized read
+        } else {
+            return 0;
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/autotest/src/main/java/Racerd.json
@@ -0,0 +1,146 @@
+[
+    {
+        "access": "hJWmvgAAAJMAAAApAAAAfgAAAHSwkNAnZGVwb3NpdKCgQCNpbnRAk6AnQWNjb3VudECQoEAkdm9pZECgoJKgIECwXAD/kgkiYXV0b3Rlc3Qvc3JjL21haW4vamF2YS9SYWNlcmQuamF2YZGgoJGwAjafTBegJHRoaXNAkAQcoKOglJOgBBpAsEBAQEAEAaCRkTBBY2NvdW50Lm1CYWxhbmNlQKAEF0A=",
+        "bug_class": "PROVER",
+        "bug_trace": [
+            {
+                "column_number": -1,
+                "description": "access to `this.Account.mBalance`",
+                "filename": "autotest/src/main/java/Racerd.java",
+                "level": 0,
+                "line_number": 28
+            }
+        ],
+        "bug_type": "THREAD_SAFETY_VIOLATION",
+        "bug_type_hum": "Thread Safety Violation",
+        "censored_reason": "",
+        "column": -1,
+        "file": "autotest/src/main/java/Racerd.java",
+        "hash": "6b62cb17008a3135d218108fa3123402",
+        "key": "Racerd.java|deposit|THREAD_SAFETY_VIOLATION",
+        "kind": "ERROR",
+        "line": 28,
+        "node_key": "9c5d6d9028928346cc4fb44cced5dea1",
+        "procedure": "void Account.deposit(int)",
+        "procedure_id": "Account.deposit(int):void.a9cc1805c1e3652887a5ee12b55803af",
+        "procedure_start_line": 0,
+        "qualifier": "Unprotected write. Non-private method `void Account.deposit(int)` writes to field `this.Account.mBalance` outside of synchronization.\n Reporting because the current class is annotated `@ThreadSafe`, so we assume that this method can run in parallel with other non-private methods in the class (including itself).",
+        "severity": "HIGH",
+        "visibility": "user"
+    },
+    {
+        "access": "hJWmvgAAAKYAAAApAAAAhQAAAHqwkNAqbWFrZURpbm5lckCToCZSYWNlcmRAkKBAJHZvaWRAoKCQ0Clib2lsV2F0ZXJAk6AEC0AECkCwTQD/kgkiYXV0b3Rlc3Qvc3JjL21haW4vamF2YS9SYWNlcmQuamF2YZGgoJGwAjafTBegJHRoaXNAkAQboKOglJOgBBxAsEBAQEAEAaCRkTNSYWNlcmQubVRlbXBlcmF0dXJlQKCwUQD/BBdA",
+        "bug_class": "PROVER",
+        "bug_trace": [
+            {
+                "column_number": -1,
+                "description": "call to void Racerd.boilWater()",
+                "filename": "autotest/src/main/java/Racerd.java",
+                "level": 0,
+                "line_number": 13
+            },
+            {
+                "column_number": -1,
+                "description": "access to `this.Racerd.mTemperature`",
+                "filename": "autotest/src/main/java/Racerd.java",
+                "level": 1,
+                "line_number": 17
+            }
+        ],
+        "bug_type": "THREAD_SAFETY_VIOLATION",
+        "bug_type_hum": "Thread Safety Violation",
+        "censored_reason": "",
+        "column": -1,
+        "file": "autotest/src/main/java/Racerd.java",
+        "hash": "2882383086ab102a88144ae3c2cc4701",
+        "key": "Racerd.java|makeDinner|THREAD_SAFETY_VIOLATION",
+        "kind": "ERROR",
+        "line": 13,
+        "node_key": "9c5d6d9028928346cc4fb44cced5dea1",
+        "procedure": "void Racerd.makeDinner()",
+        "procedure_id": "Racerd.makeDinner():void.2796f75396b30d2d49b24ddfab722306",
+        "procedure_start_line": 0,
+        "qualifier": "Unprotected write. Non-private method `void Racerd.makeDinner()` indirectly writes to field `this.Racerd.mTemperature` outside of synchronization.\n Reporting because the current class is annotated `@ThreadSafe`, so we assume that this method can run in parallel with other non-private methods in the class (including itself).",
+        "severity": "HIGH",
+        "visibility": "user"
+    },
+    {
+        "access": "hJWmvgAAAJgAAAAqAAAAgwAAAHqwkNAod2l0aGRyYXegoEAjaW50QJOgJ0FjY291bnRAkKBABAZAoKCSoCBAsGMA/5IJImF1dG90ZXN0L3NyYy9tYWluL2phdmEvUmFjZXJkLmphdmGQoKCRsAI2n0wXoCR0aGlzQJAEG6CjoJSToAQZQLBAQEBABAGgkZEwQWNjb3VudC5tQmFsYW5jZUCgBBegsGIA/wQYQA==",
+        "bug_class": "PROVER",
+        "bug_trace": [
+            {
+                "column_number": -1,
+                "description": "<Read trace>",
+                "filename": "autotest/src/main/java/Racerd.java",
+                "level": 0,
+                "line_number": 35
+            },
+            {
+                "column_number": -1,
+                "description": "access to `this.Account.mBalance`",
+                "filename": "autotest/src/main/java/Racerd.java",
+                "level": 0,
+                "line_number": 35
+            },
+            {
+                "column_number": -1,
+                "description": "<Write trace>",
+                "filename": "autotest/src/main/java/Racerd.java",
+                "level": 0,
+                "line_number": 34
+            },
+            {
+                "column_number": -1,
+                "description": "access to `this.Account.mBalance`",
+                "filename": "autotest/src/main/java/Racerd.java",
+                "level": 0,
+                "line_number": 34
+            }
+        ],
+        "bug_type": "THREAD_SAFETY_VIOLATION",
+        "bug_type_hum": "Thread Safety Violation",
+        "censored_reason": "",
+        "column": -1,
+        "file": "autotest/src/main/java/Racerd.java",
+        "hash": "5665f12d2392f93f11f556cd1b1e238a",
+        "key": "Racerd.java|withdraw|THREAD_SAFETY_VIOLATION",
+        "kind": "ERROR",
+        "line": 35,
+        "node_key": "9c5d6d9028928346cc4fb44cced5dea1",
+        "procedure": "int Account.withdraw(int)",
+        "procedure_id": "Account.withdraw(int):int.038de5054c5c25e60d169e42e0177a16",
+        "procedure_start_line": 0,
+        "qualifier": "Read/Write race. Non-private method `int Account.withdraw(int)` reads without synchronization from `this.Account.mBalance`. Potentially races with write in method `Account.withdraw(...)`.\n Reporting because the current class is annotated `@ThreadSafe`, so we assume that this method can run in parallel with other non-private methods in the class (including itself).",
+        "severity": "HIGH",
+        "visibility": "user"
+    },
+    {
+        "access": "hJWmvgAAAJEAAAAoAAAAfAAAAHOwkNAod2l0aGRyYXegoEAjaW50QJOgJ0FjY291bnRAkKBABAZAoKCSoCBAsGIA/5IJImF1dG90ZXN0L3NyYy9tYWluL2phdmEvUmFjZXJkLmphdmGRoKCRsAI2n0wXoCR0aGlzQJAEG6CjoJSToAQZQLBAQEBABAGgkZEwQWNjb3VudC5tQmFsYW5jZUCgBBdA",
+        "bug_class": "PROVER",
+        "bug_trace": [
+            {
+                "column_number": -1,
+                "description": "access to `this.Account.mBalance`",
+                "filename": "autotest/src/main/java/Racerd.java",
+                "level": 0,
+                "line_number": 34
+            }
+        ],
+        "bug_type": "THREAD_SAFETY_VIOLATION",
+        "bug_type_hum": "Thread Safety Violation",
+        "censored_reason": "",
+        "column": -1,
+        "file": "autotest/src/main/java/Racerd.java",
+        "hash": "a7c30fd1b251d9e16750fc7e5913b885",
+        "key": "Racerd.java|withdraw|THREAD_SAFETY_VIOLATION",
+        "kind": "ERROR",
+        "line": 34,
+        "node_key": "9c5d6d9028928346cc4fb44cced5dea1",
+        "procedure": "int Account.withdraw(int)",
+        "procedure_id": "Account.withdraw(int):int.038de5054c5c25e60d169e42e0177a16",
+        "procedure_start_line": 0,
+        "qualifier": "Unprotected write. Non-private method `int Account.withdraw(int)` writes to field `this.Account.mBalance` outside of synchronization.\n Reporting because the current class is annotated `@ThreadSafe`, so we assume that this method can run in parallel with other non-private methods in the class (including itself).",
+        "severity": "HIGH",
+        "visibility": "user"
+    }
+]
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/autotest/src/main/java/Starvation.java
@@ -0,0 +1,25 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Examples taken from the infer website.
+public class Starvation {
+
+    String lockA, lockB;
+
+    public void lockAThenB() {
+        synchronized(lockA) {
+            synchronized(lockB) {
+                // do something with both resources
+            }
+        }
+    }
+
+    public void lockBThenA() {
+        synchronized(lockB) {
+            synchronized(lockA) {
+                // do something with both resources
+            }
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/autotest/src/main/java/Starvation.json
@@ -0,0 +1,65 @@
+[
+    {
+        "bug_class": "PROVER",
+        "bug_trace": [
+            {
+                "column_number": -1,
+                "description": "[Trace 1] `void Starvation.lockAThenB()`",
+                "filename": "autotest/src/main/java/Starvation.java",
+                "level": 0,
+                "line_number": 11
+            },
+            {
+                "column_number": -1,
+                "description": "locks `this.Starvation.lockA` in class `Starvation*`",
+                "filename": "autotest/src/main/java/Starvation.java",
+                "level": 0,
+                "line_number": 11
+            },
+            {
+                "column_number": -1,
+                "description": "locks `this.Starvation.lockB` in class `Starvation*`",
+                "filename": "autotest/src/main/java/Starvation.java",
+                "level": 1,
+                "line_number": 12
+            },
+            {
+                "column_number": -1,
+                "description": "[Trace 2] `void Starvation.lockBThenA()`",
+                "filename": "autotest/src/main/java/Starvation.java",
+                "level": 0,
+                "line_number": 19
+            },
+            {
+                "column_number": -1,
+                "description": "locks `this.Starvation.lockB` in class `Starvation*`",
+                "filename": "autotest/src/main/java/Starvation.java",
+                "level": 0,
+                "line_number": 19
+            },
+            {
+                "column_number": -1,
+                "description": "locks `this.Starvation.lockA` in class `Starvation*`",
+                "filename": "autotest/src/main/java/Starvation.java",
+                "level": 1,
+                "line_number": 20
+            }
+        ],
+        "bug_type": "DEADLOCK",
+        "bug_type_hum": "Deadlock",
+        "censored_reason": "",
+        "column": -1,
+        "file": "autotest/src/main/java/Starvation.java",
+        "hash": "043d28a94431b4c573b949b8570fb318",
+        "key": "Starvation.java|lockAThenB|DEADLOCK",
+        "kind": "ERROR",
+        "line": 11,
+        "node_key": "9c5d6d9028928346cc4fb44cced5dea1",
+        "procedure": "void Starvation.lockAThenB()",
+        "procedure_id": "Starvation.lockAThenB():void.b7eb3955306c498af42d6336f52a796f",
+        "procedure_start_line": 0,
+        "qualifier": "Potential deadlock.\nTrace 1 (starts at `void Starvation.lockAThenB()`) first locks `this.Starvation.lockA` in class `Starvation*` (line 11 in `void Starvation.lockAThenB()`) and then locks `this.Starvation.lockB` in class `Starvation*` (line 12 in `void Starvation.lockAThenB()`).\nTrace 2 (starts at `void Starvation.lockBThenA()`), first locks `this.Starvation.lockB` in class `Starvation*` (line 19 in `void Starvation.lockBThenA()`) and then locks `this.Starvation.lockA` in class `Starvation*` (line 20 in `void Starvation.lockBThenA()`).",
+        "severity": "HIGH",
+        "visibility": "user"
+    }
+]
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/build.gradle
@@ -0,0 +1,6 @@
+allprojects {
+    // Expose the per-object-directory configuration to all projects.
+    ext {
+        topobjdir = gradle.mozconfig.topobjdir
+    }
+}
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.parallel=true
+org.gradle.daemon=true
+org.gradle.jvmargs=-Xmx2560M
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..01b8bf6b1f99cad9213fc495b33ad5bbab8efd20
GIT binary patch
literal 54329
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
bJ^ynAMotn0^tb<Ec>B|RYueZI+ur{Jl(6YG
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
+distributionSha256Sum=7a2c66d1a78f811d5f37d14630ad21cec5e77a2a4dc61e787e2257a6341016ce
\ No newline at end of file
new file mode 100755
--- /dev/null
+++ b/tools/infer/test/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/java.configure
@@ -0,0 +1,22 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+include('../../../build/moz.configure/java_common.configure')
+
+@depends(javac)
+@checking('for javac version')
+@imports('subprocess')
+def javac_version(javac):
+    try:
+        output = subprocess.check_output([javac, '-version'],
+                                         stderr=subprocess.STDOUT).rstrip()
+        version = Version(output.split(' ')[-1])
+        if version < '1.7':
+            die('javac 1.7 or higher is required (found %s). '
+                'Check the JAVA_HOME environment variable.' % version)
+        return version
+    except subprocess.CalledProcessError as e:
+        die('Failed to get javac version: %s', e.output)
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/moz.configure
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+@depends(build_project)
+def java_include(build_project):
+    # if mobile/android is enabled then the moz.configure from ./mobile
+    # will include java
+    if build_project == 'mobile/android':
+        return None
+    return 'java.configure'
+
+include(java_include)
new file mode 100644
--- /dev/null
+++ b/tools/infer/test/settings.gradle
@@ -0,0 +1,24 @@
+// Check out root/settings.gradle for more information
+
+rootProject.name = 'infer'
+
+def topsrcdir = rootProject.projectDir.absolutePath + '/../../..'
+
+def commandLine = ["${topsrcdir}/mach", "environment", "--format", "json", "--verbose"]
+def proc = commandLine.execute(null, new File(topsrcdir))
+def standardOutput = new ByteArrayOutputStream()
+proc.consumeProcessOutput(standardOutput, standardOutput)
+proc.waitFor()
+
+if (proc.exitValue() != 0) {
+    throw new GradleException("Process '${commandLine}' finished with non-zero exit value ${proc.exitValue()}:\n\n${standardOutput.toString()}")
+}
+
+import groovy.json.JsonSlurper
+def slurper = new JsonSlurper()
+def json = slurper.parseText(standardOutput.toString())
+
+gradle.ext.mozconfig = json
+
+include 'autotest'
+project(':autotest').projectDir = new File("${json.topsrcdir}/tools/infer/test/autotest")