Reviewed By: martinoluca Differential Revision: D2626393 fb-gh-sync-id: 4c54703master
parent
a84d23d4ae
commit
9466aeaef3
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"skip_translation": [
|
||||||
|
{
|
||||||
|
"language": "Java",
|
||||||
|
"source_contains": "_SHOULD_BE_SKIPPED_"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
INFER_ROOT="$SCRIPT_DIR/../"
|
||||||
|
PLATFORM="$(uname)"
|
||||||
|
|
||||||
|
function usage() {
|
||||||
|
echo "Usage: $0 [targets]"
|
||||||
|
echo
|
||||||
|
echo " targets:"
|
||||||
|
echo " all build everything"
|
||||||
|
echo " clang build clang support (C/Objective-C)"
|
||||||
|
echo " java build Java support"
|
||||||
|
echo
|
||||||
|
echo " examples:"
|
||||||
|
echo " $0 all # build Java and C/Objective-C support"
|
||||||
|
echo " $0 java clang # equivalent way of doing the above"
|
||||||
|
echo " $0 java # build Java support only"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $# == 0 ]]; then
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILD_JAVA=0
|
||||||
|
BUILD_CLANG=0
|
||||||
|
while [[ $# > 0 ]]; do
|
||||||
|
opt_key="$1"
|
||||||
|
case $opt_key in
|
||||||
|
all)
|
||||||
|
BUILD_CLANG=1
|
||||||
|
BUILD_JAVA=1
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
clang)
|
||||||
|
BUILD_CLANG=1
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
java)
|
||||||
|
BUILD_JAVA=1
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
check_installed () {
|
||||||
|
local CMD=$1
|
||||||
|
if ! which $1 >/dev/null 2>&1; then
|
||||||
|
echo "dependency not found: $CMD"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_version () {
|
||||||
|
local CMD=$1
|
||||||
|
local VERSION=$2
|
||||||
|
if ! $1 2>&1 | grep -e "$VERSION" >/dev/null 2>&1; then
|
||||||
|
echo "version mismatch: the output of \"$CMD\" does not match \"$VERSION\""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
check_installed opam
|
||||||
|
|
||||||
|
opam switch 4.01.0 -y
|
||||||
|
opam install -y \
|
||||||
|
atdgen.1.6.0 \
|
||||||
|
extlib.1.5.4 \
|
||||||
|
javalib.2.3.1 \
|
||||||
|
sawja.1.5.1
|
||||||
|
|
||||||
|
# Java-specific dependencies
|
||||||
|
if [ "$BUILD_JAVA" == "1" ]; then
|
||||||
|
check_installed javac
|
||||||
|
check_version "javac -version" "\b1\.[78]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# OSX-specific dependencies
|
||||||
|
if [ "$PLATFORM" == "Darwin" ]; then
|
||||||
|
check_installed xcodebuild
|
||||||
|
check_version "xcodebuild -version" "\(\b6\.[1-9]\+\|\b7\.[0-9]\+\)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# prepare build targets
|
||||||
|
TARGETS=""
|
||||||
|
if [ "$BUILD_JAVA" = "1" ]; then
|
||||||
|
TARGETS+=" java"
|
||||||
|
fi
|
||||||
|
if [ "$BUILD_CLANG" = "1" ]; then
|
||||||
|
TARGETS+=" clang"
|
||||||
|
if [ ! -f ".release" ]; then
|
||||||
|
./facebook-clang-plugins/clang/setup.sh
|
||||||
|
./compile-fcp.sh
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
make -C infer clean $TARGETS
|
@ -0,0 +1,203 @@
|
|||||||
|
#!/usr/bin/env python2.7
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
CURRENT_DIR = os.getcwd()
|
||||||
|
REPORT_JSON = 'report.json'
|
||||||
|
|
||||||
|
INFER = 'infer'
|
||||||
|
|
||||||
|
RECORD_ENV = 'INFER_RECORD_INTEGRATION_TESTS'
|
||||||
|
|
||||||
|
FILE = 'file'
|
||||||
|
HASH = 'hash'
|
||||||
|
LINE = 'line'
|
||||||
|
PROCEDURE = 'procedure'
|
||||||
|
TYPE = 'type'
|
||||||
|
REPORT_FIELDS = [
|
||||||
|
FILE,
|
||||||
|
PROCEDURE,
|
||||||
|
TYPE,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def should_record_tests():
|
||||||
|
return RECORD_ENV in os.environ and os.environ[RECORD_ENV] == '1'
|
||||||
|
|
||||||
|
|
||||||
|
def quote(s):
|
||||||
|
return '\"{}\"'.format(s)
|
||||||
|
|
||||||
|
|
||||||
|
def string_of_error(e):
|
||||||
|
msg = e[TYPE] + ' in file ' + quote(e[FILE])
|
||||||
|
msg += ', procedure ' + quote(e[PROCEDURE])
|
||||||
|
if LINE in e:
|
||||||
|
msg += ' on line ' + e[LINE]
|
||||||
|
return msg
|
||||||
|
|
||||||
|
|
||||||
|
def load_report(filename):
|
||||||
|
with open(filename, 'r') as file_in:
|
||||||
|
return json.load(file_in)
|
||||||
|
|
||||||
|
|
||||||
|
def save_report(reports, filename):
|
||||||
|
with open(filename, 'w') as file_out:
|
||||||
|
filtered = []
|
||||||
|
for report in reports:
|
||||||
|
r = {}
|
||||||
|
for key in REPORT_FIELDS:
|
||||||
|
if key in report:
|
||||||
|
r[key] = report[key]
|
||||||
|
if len(r) > 0:
|
||||||
|
filtered.append(r)
|
||||||
|
return json.dump(filtered, file_out, indent=2, separators=(',', ': '))
|
||||||
|
|
||||||
|
|
||||||
|
def run_analysis(root, clean_cmd, build_cmd, analyzer):
|
||||||
|
|
||||||
|
os.chdir(root)
|
||||||
|
|
||||||
|
subprocess.check_call(clean_cmd)
|
||||||
|
|
||||||
|
temp_out_dir = tempfile.mkdtemp(suffix='_out', prefix='infer_')
|
||||||
|
infer_cmd = ['infer', '-a', analyzer, '-o', temp_out_dir, '--'] + build_cmd
|
||||||
|
|
||||||
|
with tempfile.TemporaryFile(
|
||||||
|
mode='w',
|
||||||
|
suffix='.out',
|
||||||
|
prefix='analysis_') as analysis_output:
|
||||||
|
subprocess.check_call(infer_cmd, stdout=analysis_output)
|
||||||
|
|
||||||
|
found_errors = load_report(os.path.join(temp_out_dir, REPORT_JSON))
|
||||||
|
shutil.rmtree(temp_out_dir)
|
||||||
|
os.chdir(CURRENT_DIR)
|
||||||
|
|
||||||
|
return found_errors
|
||||||
|
|
||||||
|
|
||||||
|
def match_pattern(f, p):
|
||||||
|
for key in p.keys():
|
||||||
|
if f[key] != p[key]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def is_expected(e, patterns):
|
||||||
|
for p in patterns:
|
||||||
|
if match_pattern(e, p):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def is_missing(p, errors):
|
||||||
|
for e in errors:
|
||||||
|
if match_pattern(e, p):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def unexpected_errors(errors, patterns):
|
||||||
|
return [e for e in errors if not is_expected(e, patterns)]
|
||||||
|
|
||||||
|
|
||||||
|
def missing_errors(errors, patterns):
|
||||||
|
return [p for p in patterns if is_missing(p, errors)]
|
||||||
|
|
||||||
|
|
||||||
|
def check_results(errors, patterns):
|
||||||
|
unexpected = unexpected_errors(errors, patterns)
|
||||||
|
if unexpected != []:
|
||||||
|
print('\nInfer found the following unexpected errors:')
|
||||||
|
for e in unexpected:
|
||||||
|
print('\t{}\n'.format(string_of_error(e)))
|
||||||
|
missing = missing_errors(errors, patterns)
|
||||||
|
if missing != []:
|
||||||
|
print('\nInfer did not find the following errors:')
|
||||||
|
for p in missing:
|
||||||
|
print('\t{}\n'.format(string_of_error(p)))
|
||||||
|
assert unexpected == []
|
||||||
|
assert missing == []
|
||||||
|
|
||||||
|
|
||||||
|
def is_tool_available(cmd):
|
||||||
|
try:
|
||||||
|
subprocess.call(cmd)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == os.errno.ENOENT:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def do_test(errors, expected_errors_filename):
|
||||||
|
if should_record_tests():
|
||||||
|
save_report(errors, expected_errors_filename)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
patterns = load_report(expected_errors_filename)
|
||||||
|
check_results(errors, patterns)
|
||||||
|
|
||||||
|
|
||||||
|
class BuildIntegrationTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_ant_integration(self):
|
||||||
|
if is_tool_available(['ant', '-version']):
|
||||||
|
print('\nRunning Gradle integration test')
|
||||||
|
root = os.path.join(CURRENT_DIR, 'infer', 'tests')
|
||||||
|
errors = run_analysis(
|
||||||
|
root,
|
||||||
|
['ant', 'clean'],
|
||||||
|
['ant', 'compile'],
|
||||||
|
INFER)
|
||||||
|
do_test(errors, os.path.join(root, 'ant_report.json'))
|
||||||
|
else:
|
||||||
|
print('\nSkipping Ant integration test')
|
||||||
|
assert True
|
||||||
|
|
||||||
|
def test_gradle_integration(self):
|
||||||
|
if is_tool_available(['gradle', '--version']):
|
||||||
|
print('\nRunning Gradle integration test')
|
||||||
|
root = os.path.join(CURRENT_DIR, 'examples', 'android_hello')
|
||||||
|
errors = run_analysis(
|
||||||
|
root,
|
||||||
|
['gradle', 'clean'],
|
||||||
|
['gradle', 'build'],
|
||||||
|
INFER)
|
||||||
|
do_test(errors, os.path.join(root, 'gradle_report.json'))
|
||||||
|
else:
|
||||||
|
print('\nSkipping Gradle integration test')
|
||||||
|
assert True
|
||||||
|
|
||||||
|
def test_buck_integration(self):
|
||||||
|
if is_tool_available(['buck', '--version']):
|
||||||
|
print('\nRunning Buck integration test')
|
||||||
|
root = CURRENT_DIR
|
||||||
|
errors = run_analysis(
|
||||||
|
root,
|
||||||
|
['buck', 'clean'],
|
||||||
|
['buck', 'build', 'infer'],
|
||||||
|
INFER)
|
||||||
|
report_path = os.path.join(
|
||||||
|
CURRENT_DIR, 'infer', 'tests', 'buck_report.json')
|
||||||
|
do_test(errors, report_path)
|
||||||
|
else:
|
||||||
|
print('\nSkipping Buck integration test')
|
||||||
|
assert True
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main() # run all the tests
|
@ -1,59 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Copyright (c) 2014 - 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.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
parent=$(dirname "$0")
|
|
||||||
SCRIPT_DIR=$( cd "$parent" && pwd )
|
|
||||||
README_MSG="To get and compile facebook-clang-plugins, please consult the README file."
|
|
||||||
|
|
||||||
function echoerr {
|
|
||||||
echo $@ >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
# Counting the passed arguments
|
|
||||||
if [ "$#" -lt 1 ]; then
|
|
||||||
echoerr "Error: not enough arguments."
|
|
||||||
echoerr "USAGE: $0 <facebook-clang-plugins root>"
|
|
||||||
echoerr "$README_MSG"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
REPO_DIR=$1
|
|
||||||
|
|
||||||
# Check that the directory passed in input exists
|
|
||||||
([ -d "$REPO_DIR" ] && [ -d "$REPO_DIR/libtooling" ]) || {
|
|
||||||
echoerr "$REPO_DIR does not exist or is invalid.";
|
|
||||||
echoerr "Please check that the path to facebook-clang-plugins is correct.";
|
|
||||||
echoerr "$README_MSG";
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSION_FILE="$SCRIPT_DIR/../dependencies/clang-plugin/clang-plugin-version.config"
|
|
||||||
|
|
||||||
cd $REPO_DIR
|
|
||||||
[ ! -d ".git" ] && {
|
|
||||||
echoerr "SKIPPING the facebook-clang-plugins version check since";
|
|
||||||
echoerr "$REPO_DIR is NOT a Git repository";
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
echoerr "Checking that the revision of facebook-clang-plugins is correct..."
|
|
||||||
GIT_CURRENT_REVISION=$(git log --pretty=format:'%H' -n 1)
|
|
||||||
GIT_EXPECTED_REVISION=$(cat "$VERSION_FILE")
|
|
||||||
|
|
||||||
echoerr "Current revision is $GIT_CURRENT_REVISION"
|
|
||||||
echoerr "Expected revision is $GIT_EXPECTED_REVISION"
|
|
||||||
|
|
||||||
if [ "$GIT_CURRENT_REVISION" != "$GIT_EXPECTED_REVISION" ]; then
|
|
||||||
echoerr "Revisions mismatching. Please, run update-fcp.sh to get the revision needed by Infer."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echoerr "Clang plugin is up to date! Continue..."
|
|
||||||
fi
|
|
Loading…
Reference in new issue