diff --git a/.travis.yml b/.travis.yml index b8527d7..0edbe71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,35 +8,30 @@ matrix: python: 2.7 env: - TRAVIS_CLANG=clang-4.0 - - TRAVIS_CLANGPP=clang++-4.0 - os: linux dist: trusty sudo: false python: 3.3 env: - TRAVIS_CLANG=clang-4.0 - - TRAVIS_CLANGPP=clang++-4.0 - os: linux dist: trusty sudo: false python: 3.4 env: - TRAVIS_CLANG=clang-4.0 - - TRAVIS_CLANGPP=clang++-4.0 - os: linux dist: trusty sudo: false python: 3.5 env: - TRAVIS_CLANG=clang-4.0 - - TRAVIS_CLANGPP=clang++-4.0 - os: linux dist: trusty sudo: false python: 3.6 env: - TRAVIS_CLANG=clang-4.0 - - TRAVIS_CLANGPP=clang++-4.0 - os: osx osx_image: xcode6.4 language: generic @@ -54,6 +49,9 @@ addons: - ubuntu-toolchain-r-test packages: - clang-4.0 + - cmake + - scons + - qt4-qmake before_install: - uname diff --git a/appveyor.yml b/appveyor.yml index b3d9fdd..2417ac4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -43,6 +43,12 @@ install: # about it being out of date. - "pip install --disable-pip-version-check --user --upgrade pip" + # Install the build dependencies of the project. If some dependencies contain + # compiled extensions and are not provided as pre-built wheel packages, + # pip will build them from source using the MSVC compiler matching the + # target Python version and architecture + - "pip install pep8 lit" + build_script: # Build the compiled extension - "pip install ." diff --git a/libear/ear.c b/libear/ear.c index b35746d..fd830ae 100644 --- a/libear/ear.c +++ b/libear/ear.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -415,6 +416,11 @@ static void bear_report_call(char const *const argv[]) { return; pthread_mutex_lock(&mutex); + char const * const saved_locale = strdup(setlocale(LC_ALL, NULL)); + if (0 == saved_locale) { + perror("bear: strdup for locale"); + exit(EXIT_FAILURE); + } const char *cwd = getcwd(NULL, 0); if (0 == cwd) { perror("bear: getcwd"); @@ -441,23 +447,28 @@ static void bear_report_call(char const *const argv[]) { exit(EXIT_FAILURE); } free((void *)cwd); + // Restore locale. + setlocale(LC_ALL, saved_locale); + free((void *)saved_locale); pthread_mutex_unlock(&mutex); } static int bear_write_json_report(int fd, char const *const cmd[], char const *const cwd, pid_t pid) { + setlocale(LC_ALL, "en_US.UTF-8"); + if (0 > dprintf(fd, "{ \"pid\": %d, \"cmd\": [", pid)) return -1; for (char const *const *it = cmd; (it) && (*it); ++it) { char const *const sep = (it != cmd) ? "," : ""; - const size_t buffer_size = 2 * strlen(*it); + const size_t buffer_size = 6 * strlen(*it); char buffer[buffer_size]; if (-1 == bear_encode_json_string(*it, buffer, buffer_size)) return -1; if (0 > dprintf(fd, "%s \"%s\"", sep, buffer)) return -1; } - const size_t buffer_size = 2 * strlen(cwd); + const size_t buffer_size = 6 * strlen(cwd); char buffer[buffer_size]; if (-1 == bear_encode_json_string(cwd, buffer, buffer_size)) return -1; @@ -468,55 +479,60 @@ static int bear_write_json_report(int fd, char const *const cmd[], char const *c } static int bear_encode_json_string(char const *const src, char *const dst, size_t const dst_size) { - char const *src_it = src; - char const *const src_end = src + strlen(src); + size_t const wsrc_length = mbstowcs(NULL, src, 0); + wchar_t wsrc[wsrc_length + 1]; + if (mbstowcs((wchar_t *)&wsrc, src, wsrc_length + 1) != wsrc_length) { + perror("bear: mbstowcs"); + return -1; + } + wchar_t const *wsrc_it = (wchar_t const *)&wsrc; + wchar_t const *const wsrc_end = wsrc_it + wsrc_length; char *dst_it = dst; char *const dst_end = dst + dst_size; - for (; src_it != src_end; ++src_it, ++dst_it) { - if (dst_it == dst_end) + for (; wsrc_it != wsrc_end; ++wsrc_it) { + if (dst_it >= dst_end) { return -1; - // Insert an escape character before control characters. - switch (*src_it) { - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - case '"': - case '\\': - *dst_it++ = '\\'; - break; - default: - break; } - // Transform some of the control characters. - switch (*src_it) { - case '\b': - *dst_it = 'b'; + // Insert an escape character before control characters. + switch (*wsrc_it) { + case L'\b': + dst_it += snprintf(dst_it, 3, "\\b"); break; - case '\f': - *dst_it = 'f'; + case L'\f': + dst_it += snprintf(dst_it, 3, "\\f"); break; - case '\n': - *dst_it = 'n'; + case L'\n': + dst_it += snprintf(dst_it, 3, "\\n"); break; - case '\r': - *dst_it = 'r'; + case L'\r': + dst_it += snprintf(dst_it, 3, "\\r"); break; - case '\t': - *dst_it = 't'; + case L'\t': + dst_it += snprintf(dst_it, 3, "\\t"); + break; + case L'"': + dst_it += snprintf(dst_it, 3, "\\\""); + break; + case L'\\': + dst_it += snprintf(dst_it, 3, "\\\\"); break; default: - *dst_it = *src_it; + if ((*wsrc_it < L' ') || (*wsrc_it > 127)) { + dst_it += snprintf(dst_it, 7, "\\u%04x", (unsigned int)*wsrc_it); + } else { + *dst_it++ = (char)*wsrc_it; + } + break; } } - if (dst_it == dst_end) - return -1; - // Insert a terminating 0 value. - *dst_it = 0; - return 0; + if (dst_it < dst_end) { + // Insert a terminating 0 value. + *dst_it = 0; + return 0; + } + return -1; } /* update environment assure that chilren processes will copy the desired diff --git a/tests/functional/cases/analyze/analyze_architecture_specified.fts b/tests/functional/cases/analyze/analyze_architecture_specified.fts index dc7bffd..7610450 100644 --- a/tests/functional/cases/analyze/analyze_architecture_specified.fts +++ b/tests/functional/cases/analyze/analyze_architecture_specified.fts @@ -20,7 +20,7 @@ mkdir -p "${root_dir}/src" touch "${root_dir}/src/empty.c" -cat >> "${root_dir}/input.json" << EOF +cat > "${root_dir}/input.json" << EOF [ { "directory": "${root_dir}", @@ -46,7 +46,7 @@ cat >> "${root_dir}/input.json" << EOF EOF checker_file="${root_dir}/check.sh" -cat >> ${checker_file} << EOF +cat > ${checker_file} << EOF #!/usr/bin/env bash set -o errexit diff --git a/tests/functional/cases/analyze/analyze_debug_code.fts b/tests/functional/cases/analyze/analyze_debug_code.fts index 72801fd..02ab108 100644 --- a/tests/functional/cases/analyze/analyze_debug_code.fts +++ b/tests/functional/cases/analyze/analyze_debug_code.fts @@ -18,7 +18,7 @@ set -o xtrace root_dir=$1 mkdir -p "${root_dir}/src" -cat >> "${root_dir}/src/broken.c" << EOF +cat > "${root_dir}/src/broken.c" << EOF #if NDEBUG #else EOF @@ -28,7 +28,7 @@ cat >> "${root_dir}/src/broken.c" << EOF EOF build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset diff --git a/tests/functional/cases/analyze/analyze_disable_checkers.fts b/tests/functional/cases/analyze/analyze_disable_checkers.fts index d7abf4e..79b6bfc 100644 --- a/tests/functional/cases/analyze/analyze_disable_checkers.fts +++ b/tests/functional/cases/analyze/analyze_disable_checkers.fts @@ -19,7 +19,7 @@ mkdir -p "${root_dir}/src" cp "${test_input_dir}/div_zero.c" "${root_dir}/src/broken.c" -cat >> "${root_dir}/input.json" << EOF +cat > "${root_dir}/input.json" << EOF [ { "directory": "${root_dir}", diff --git a/tests/functional/cases/analyze/analyze_enable_checkers.fts b/tests/functional/cases/analyze/analyze_enable_checkers.fts index 70bcb9b..c512493 100644 --- a/tests/functional/cases/analyze/analyze_enable_checkers.fts +++ b/tests/functional/cases/analyze/analyze_enable_checkers.fts @@ -20,7 +20,7 @@ mkdir -p "${root_dir}/src" touch "${root_dir}/src/empty.c" -cat >> "${root_dir}/input.json" << EOF +cat > "${root_dir}/input.json" << EOF [ { "directory": "${root_dir}", @@ -31,7 +31,7 @@ cat >> "${root_dir}/input.json" << EOF EOF checker_file="${root_dir}/check.sh" -cat >> ${checker_file} << EOF +cat > ${checker_file} << EOF #!/usr/bin/env bash set -o errexit diff --git a/tests/functional/cases/analyze/analyze_exclude_files.fts b/tests/functional/cases/analyze/analyze_exclude_files.fts index 8af077a..8cf79fa 100644 --- a/tests/functional/cases/analyze/analyze_exclude_files.fts +++ b/tests/functional/cases/analyze/analyze_exclude_files.fts @@ -30,7 +30,7 @@ touch "${root_dir}/src/empty.c" touch "${root_dir}/src/ignore/empty.c" build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset @@ -45,7 +45,7 @@ EOF chmod +x ${build_file} checker_file="${root_dir}/check.sh" -cat >> ${checker_file} << EOF +cat > ${checker_file} << EOF #!/usr/bin/env bash set -o errexit diff --git a/tests/functional/cases/analyze/analyze_ignore_configure.fts b/tests/functional/cases/analyze/analyze_ignore_configure.fts index dbd74ed..d1834e7 100644 --- a/tests/functional/cases/analyze/analyze_ignore_configure.fts +++ b/tests/functional/cases/analyze/analyze_ignore_configure.fts @@ -23,7 +23,7 @@ mkdir -p "${root_dir}/src" cp "${test_input_dir}/div_zero.c" "${root_dir}/src/broken.c" build_file="${root_dir}/configure" -cat >> "${build_file}" << EOF +cat > "${build_file}" << EOF #!/usr/bin/env bash set -o errexit @@ -36,7 +36,7 @@ EOF chmod +x "${build_file}" checker_file="${root_dir}/check.sh" -cat >> "${checker_file}" << EOF +cat > "${checker_file}" << EOF #!/usr/bin/env bash set -o errexit diff --git a/tests/functional/cases/analyze/analyze_language_specified.fts b/tests/functional/cases/analyze/analyze_language_specified.fts index 3ad994b..5bed5e8 100644 --- a/tests/functional/cases/analyze/analyze_language_specified.fts +++ b/tests/functional/cases/analyze/analyze_language_specified.fts @@ -20,7 +20,7 @@ mkdir -p "${root_dir}/src" touch "${root_dir}/src/empty.c" -cat >> "${root_dir}/input.json" << EOF +cat > "${root_dir}/input.json" << EOF [ { "directory": "${root_dir}", @@ -46,7 +46,7 @@ cat >> "${root_dir}/input.json" << EOF EOF checker_file="${root_dir}/check.sh" -cat >> ${checker_file} << EOF +cat > ${checker_file} << EOF #!/usr/bin/env bash set -o errexit diff --git a/tests/functional/cases/analyze/exit_code/exit_code_failed_shows_bugs.fts b/tests/functional/cases/analyze/exit_code/exit_code_failed_shows_bugs.fts index 5cd2a3d..3e1824e 100644 --- a/tests/functional/cases/analyze/exit_code/exit_code_failed_shows_bugs.fts +++ b/tests/functional/cases/analyze/exit_code/exit_code_failed_shows_bugs.fts @@ -20,7 +20,7 @@ mkdir -p "${root_dir}/src" cp "${test_input_dir}/div_zero.c" "${root_dir}/src/broken.c" -cat >> "${root_dir}/input.json" << EOF +cat > "${root_dir}/input.json" << EOF [ { "directory": "${root_dir}", diff --git a/tests/functional/cases/analyze/exit_code/exit_code_failed_shows_bugs_on_plist.fts b/tests/functional/cases/analyze/exit_code/exit_code_failed_shows_bugs_on_plist.fts index adbdfee..bb1e839 100644 --- a/tests/functional/cases/analyze/exit_code/exit_code_failed_shows_bugs_on_plist.fts +++ b/tests/functional/cases/analyze/exit_code/exit_code_failed_shows_bugs_on_plist.fts @@ -20,7 +20,7 @@ mkdir -p "${root_dir}/src" cp "${test_input_dir}/div_zero.c" "${root_dir}/src/broken.c" -cat >> "${root_dir}/run.sh" << EOF +cat > "${root_dir}/run.sh" << EOF #!/usr/bin/env bash set -o nounset diff --git a/tests/functional/cases/analyze/quoted_arguments.fts b/tests/functional/cases/analyze/quoted_arguments.fts index a638684..9956634 100644 --- a/tests/functional/cases/analyze/quoted_arguments.fts +++ b/tests/functional/cases/analyze/quoted_arguments.fts @@ -19,7 +19,7 @@ set -o xtrace root_dir=$1 mkdir -p "${root_dir}/src" -cat >> "${root_dir}/src/names.c" << EOF +cat > "${root_dir}/src/names.c" << EOF char const * const first = FIRST; char const * const last = LAST; @@ -32,7 +32,7 @@ int main() { EOF build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset diff --git a/tests/functional/cases/analyze/scan_runs_analyzer.fts b/tests/functional/cases/analyze/scan_runs_analyzer.fts index 86e6f90..153936b 100644 --- a/tests/functional/cases/analyze/scan_runs_analyzer.fts +++ b/tests/functional/cases/analyze/scan_runs_analyzer.fts @@ -23,7 +23,7 @@ mkdir -p "${root_dir}/src" touch "${root_dir}/src/empty.c" build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset @@ -36,7 +36,7 @@ EOF chmod +x ${build_file} checker_file="${root_dir}/check.sh" -cat >> ${checker_file} << EOF +cat > ${checker_file} << EOF #!/usr/bin/env bash set -o errexit diff --git a/tests/functional/cases/analyze/unkown_compiler_recognised.fts b/tests/functional/cases/analyze/unkown_compiler_recognised.fts new file mode 100644 index 0000000..2edd595 --- /dev/null +++ b/tests/functional/cases/analyze/unkown_compiler_recognised.fts @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +# RUN: bash %s %T/unkown_compiler_recognised +# RUN: cd %T/unkown_compiler_recognised; %{scan-build} --use-cc=%T/unkown_compiler_recognised/wrapper --use-c++=%T/unkown_compiler_recognised/wrapper++ -o . --intercept-first --override-compiler ./run.sh | ./check.sh +# RUN: cd %T/unkown_compiler_recognised; %{scan-build} --use-cc=%T/unkown_compiler_recognised/wrapper --use-c++=%T/unkown_compiler_recognised/wrapper++ -o . --override-compiler ./run.sh | ./check.sh + +set -o errexit +set -o nounset +set -o xtrace + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── wrapper +# ├── wrapper++ +# ├── run.sh +# ├── check.sh +# └── src +# └── broken.c + +root_dir=$1 +mkdir -p "${root_dir}/src" + +cp "${test_input_dir}/div_zero.c" "${root_dir}/src/broken.c" + +wrapper_file="${root_dir}/wrapper" +cat > ${wrapper_file} << EOF +#!/usr/bin/env bash + +true +EOF +chmod +x ${wrapper_file} + +wrapperxx_file="${root_dir}/wrapper++" +cat > ${wrapperxx_file} << EOF +#!/usr/bin/env bash + +true +EOF +chmod +x ${wrapperxx_file} + +build_file="${root_dir}/run.sh" +cat > ${build_file} << EOF +#!/usr/bin/env bash + +set -o nounset +set -o xtrace + +\$CC -c -o ./src/empty.o ./src/broken.c; +\$CXX -c -o ./src/empty.o ./src/broken.c; + +cd src +\$CC -c -o ./empty.o ./broken.c; +\$CXX -c -o ./empty.o ./broken.c; +EOF +chmod +x ${build_file} + +check_two="${root_dir}/check.sh" +cat > "${check_two}" << EOF +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o xtrace + +out_dir=\$(sed -n 's/\(.*\) Report directory created: \(.*\)/\2/p') +if [ -d "\$out_dir" ] +then + ls "\$out_dir/index.html" + ls \$out_dir/report-*.html +else + echo "output directory should exists" + false +fi +EOF +chmod +x "${check_two}" diff --git a/tests/functional/cases/analyze/wrapper/compiler_name_from_argument.fts b/tests/functional/cases/analyze/wrapper/compiler_name_from_argument.fts index d3363ec..140ee04 100644 --- a/tests/functional/cases/analyze/wrapper/compiler_name_from_argument.fts +++ b/tests/functional/cases/analyze/wrapper/compiler_name_from_argument.fts @@ -25,7 +25,7 @@ mkdir -p "${root_dir}/src" cp "${test_input_dir}/div_zero.c" "${root_dir}/src/broken.c" wrapper_file="${root_dir}/wrapper" -cat >> ${wrapper_file} << EOF +cat > ${wrapper_file} << EOF #!/usr/bin/env bash set -o xtrace @@ -35,7 +35,7 @@ EOF chmod +x ${wrapper_file} wrapperxx_file="${root_dir}/wrapper++" -cat >> ${wrapperxx_file} << EOF +cat > ${wrapperxx_file} << EOF #!/usr/bin/env bash set -o xtrace @@ -45,7 +45,7 @@ EOF chmod +x ${wrapperxx_file} build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset @@ -61,7 +61,7 @@ EOF chmod +x ${build_file} check_two="${root_dir}/check.sh" -cat >> "${check_two}" << EOF +cat > "${check_two}" << EOF #!/usr/bin/env bash set -o errexit diff --git a/tests/functional/cases/intercept/end-to-end/Input/SConstruct b/tests/functional/cases/intercept/end-to-end/Input/SConstruct new file mode 100644 index 0000000..2b034d0 --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/Input/SConstruct @@ -0,0 +1,12 @@ +env = Environment() +env['CXX'] = 'c++' +env['CC'] = 'cc' +env.Append(CPPDEFINES={'RELEASE_BUILD' : 'First release \"quoted\"'}) + +some_lib = env.SharedLibrary(target="some_lib", + source=["lib/foo.cpp", "lib/bar.cc"]) +some_app = env.Program(target="some_app", + source=["bin/far.cxx", "bin/boo.c++"], + CPPPATH=Split('#lib'), + LIBPATH=['.'], + LIBS=['some_lib']) diff --git a/tests/functional/cases/intercept/end-to-end/Input/bin/bin.pro b/tests/functional/cases/intercept/end-to-end/Input/bin/bin.pro new file mode 100644 index 0000000..b0e130d --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/Input/bin/bin.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +TARGET = some_app + +INCLUDEPATH += ../lib +LIBS += -L../lib -lsome_lib + +HEADERS += boo.h++ + +SOURCES += boo.c++ +SOURCES += far.cxx diff --git a/tests/functional/cases/intercept/end-to-end/Input/bin/boo.c++ b/tests/functional/cases/intercept/end-to-end/Input/bin/boo.c++ new file mode 100644 index 0000000..3eac940 --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/Input/bin/boo.c++ @@ -0,0 +1,33 @@ +#include "boo.h++" +#include + +void t2(int i); + +void t1() +{ + for (int i = 0; i < 100; ++i) + { + if (98 == i) + { + t2(i); + break; + } + } +} + +void t2(int i) +{ + if (9 == i) + { + int k = i + 9; + ++k; + return; + } + acme::t1(); +} + +int main() +{ + t1(); + return 0; +} diff --git a/tests/functional/cases/intercept/end-to-end/Input/bin/boo.h++ b/tests/functional/cases/intercept/end-to-end/Input/bin/boo.h++ new file mode 100644 index 0000000..8654424 --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/Input/bin/boo.h++ @@ -0,0 +1,6 @@ +#ifndef boo_h +#define boo_h + +void t1(); + +#endif diff --git a/tests/functional/cases/intercept/end-to-end/Input/bin/far.cxx b/tests/functional/cases/intercept/end-to-end/Input/bin/far.cxx new file mode 100644 index 0000000..ef45583 --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/Input/bin/far.cxx @@ -0,0 +1,8 @@ +#include +#include "boo.h++" + +void b1() +{ + t1(); + acme::t1(); +} diff --git a/tests/functional/cases/intercept/end-to-end/Input/lib/bar.cc b/tests/functional/cases/intercept/end-to-end/Input/lib/bar.cc new file mode 100644 index 0000000..2fbdb00 --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/Input/lib/bar.cc @@ -0,0 +1,11 @@ +#include "foo.h" + +namespace acme +{ + +void b1() +{ + t1(); +} + +} diff --git a/tests/functional/cases/intercept/end-to-end/Input/lib/foo.cpp b/tests/functional/cases/intercept/end-to-end/Input/lib/foo.cpp new file mode 100644 index 0000000..d92c1bb --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/Input/lib/foo.cpp @@ -0,0 +1,30 @@ +#include "foo.h" + +namespace acme +{ + +void t2(int i); + +void t1() +{ + for (int i = 0; i < 100; ++i) + { + if (98 == i) + { + t2(i); + break; + } + } +} + +void t2(int i) +{ + if (9 == i) + { + int k = i + 9; + --k; + return; + } +} + +} diff --git a/tests/functional/cases/intercept/end-to-end/Input/lib/foo.h b/tests/functional/cases/intercept/end-to-end/Input/lib/foo.h new file mode 100644 index 0000000..c7fab7a --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/Input/lib/foo.h @@ -0,0 +1,11 @@ +#ifndef foo_h +#define foo_h + +namespace acme +{ + +void t1(); + +} + +#endif diff --git a/tests/functional/cases/intercept/end-to-end/Input/lib/lib.pro b/tests/functional/cases/intercept/end-to-end/Input/lib/lib.pro new file mode 100644 index 0000000..16311c7 --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/Input/lib/lib.pro @@ -0,0 +1,7 @@ +TEMPLATE = lib +TARGET = some_lib + +HEADERS += foo.h + +SOURCES += foo.cpp +SOURCES += bar.cc diff --git a/tests/functional/cases/intercept/end-to-end/Input/qmake.pro b/tests/functional/cases/intercept/end-to-end/Input/qmake.pro new file mode 100644 index 0000000..51c8b79 --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/Input/qmake.pro @@ -0,0 +1,6 @@ +TEMPLATE = subdirs + +CONFIG -= qt + +SUBDIRS += lib +SUBDIRS += bin diff --git a/tests/functional/cases/intercept/end-to-end/check_files.py b/tests/functional/cases/intercept/end-to-end/check_files.py new file mode 100644 index 0000000..6edc169 --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/check_files.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +import argparse +import json +import sys +import os.path + + +EXPECTED = frozenset(['far.cxx', 'bar.cc', 'foo.cpp', 'boo.c++']) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('input', type=argparse.FileType('r')) + args = parser.parse_args() + # file is open, parse the json content + input = json.load(args.input) + # just get file names + result = set([os.path.basename(entry['file']) for entry in input]) + return 0 if result == EXPECTED else 1 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tests/functional/cases/intercept/end-to-end/qmake.ft b/tests/functional/cases/intercept/end-to-end/qmake.ft new file mode 100644 index 0000000..a5a3e24 --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/qmake.ft @@ -0,0 +1,5 @@ +# REQUIRES: qmake,preload +# RUN: mkdir -p %T/qmake_build +# RUN: cd %T/qmake_build; qmake-qt4 ../../Input/qmake.pro +# RUN: cd %T/qmake_build; %{intercept-build} --cdb qmake.json make +# RUN: %{python} %S/check_files.py %T/qmake_build/qmake.json diff --git a/tests/functional/cases/intercept/end-to-end/scons.ft b/tests/functional/cases/intercept/end-to-end/scons.ft new file mode 100644 index 0000000..0d374e1 --- /dev/null +++ b/tests/functional/cases/intercept/end-to-end/scons.ft @@ -0,0 +1,4 @@ +# REQUIRES: scons,preload +# RUN: mkdir -p %T/scons_build +# RUN: cd %T/scons_build; %{intercept-build} --cdb scons.json scons -Y ../../Input +# RUN: %{python} %S/check_files.py %T/scons_build/scons.json diff --git a/tests/functional/cases/intercept/exec_calls/run_exec_test.fts b/tests/functional/cases/intercept/exec_calls/run_exec_test.ft similarity index 90% rename from tests/functional/cases/intercept/exec_calls/run_exec_test.fts rename to tests/functional/cases/intercept/exec_calls/run_exec_test.ft index c3782a9..0e34768 100644 --- a/tests/functional/cases/intercept/exec_calls/run_exec_test.fts +++ b/tests/functional/cases/intercept/exec_calls/run_exec_test.ft @@ -1,4 +1,3 @@ -#!/usr/bin/env bash # REQUIRES: preload # RUN: cmake -B%T -H%S # RUN: make -C %T diff --git a/tests/functional/cases/intercept/broken_build.fts b/tests/functional/cases/intercept/intercept/broken_build.fts similarity index 70% rename from tests/functional/cases/intercept/broken_build.fts rename to tests/functional/cases/intercept/intercept/broken_build.fts index 35e2a17..d1d1ff6 100644 --- a/tests/functional/cases/intercept/broken_build.fts +++ b/tests/functional/cases/intercept/intercept/broken_build.fts @@ -27,45 +27,45 @@ mkdir -p "${root_dir}/src" cp "${test_input_dir}/compile_error.c" "${root_dir}/src/broken.c" build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset set -o xtrace -"\$CC" -c -o src/broken.o -Dver=1 src/broken.c; -"\$CXX" -c -o src/broken.o -Dver=2 src/broken.c; +\$CC -c -Dver=1 src/broken.c; +\$CXX -c -Dver=2 src/broken.c; cd src -"\$CC" -c -o broken.o -Dver=3 broken.c; -"\$CXX" -c -o broken.o -Dver=4 broken.c; +\$CC -c -Dver=3 broken.c; +\$CXX -c -Dver=4 broken.c; true; EOF chmod +x ${build_file} -cat >> "${root_dir}/expected.json" << EOF +cat > "${root_dir}/expected.json" << EOF [ { - "command": "cc -c -o src/broken.o -Dver=1 src/broken.c", + "command": "cc -c -Dver=1 src/broken.c", "directory": "${root_dir}", "file": "src/broken.c" } , { - "command": "c++ -c -o src/broken.o -Dver=2 src/broken.c", + "command": "c++ -c -Dver=2 src/broken.c", "directory": "${root_dir}", "file": "src/broken.c" } , { - "command": "cc -c -o broken.o -Dver=3 broken.c", + "command": "cc -c -Dver=3 broken.c", "directory": "${root_dir}/src", "file": "broken.c" } , { - "command": "c++ -c -o broken.o -Dver=4 broken.c", + "command": "c++ -c -Dver=4 broken.c", "directory": "${root_dir}/src", "file": "broken.c" } diff --git a/tests/functional/cases/intercept/clean_env_build_intercept.fts b/tests/functional/cases/intercept/intercept/clean_env_build.fts similarity index 66% rename from tests/functional/cases/intercept/clean_env_build_intercept.fts rename to tests/functional/cases/intercept/intercept/clean_env_build.fts index 97f4aa0..f8e7368 100644 --- a/tests/functional/cases/intercept/clean_env_build_intercept.fts +++ b/tests/functional/cases/intercept/intercept/clean_env_build.fts @@ -26,45 +26,45 @@ mkdir -p "${root_dir}/src" touch "${root_dir}/src/empty.c" build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset set -o xtrace -${clang} -c -o src/empty.o -Dver=1 src/empty.c; -${clangpp} -c -o src/empty.o -Dver=2 src/empty.c; +${clang} -c -Dver=1 src/empty.c; +${clangpp} -c -Dver=2 src/empty.c; cd src -${clang} -c -o empty.o -Dver=3 empty.c; -${clangpp} -c -o empty.o -Dver=4 empty.c; +${clang} -c -Dver=3 empty.c; +${clangpp} -c -Dver=4 empty.c; true; EOF chmod +x ${build_file} -cat >> "${root_dir}/expected.json" << EOF +cat > "${root_dir}/expected.json" << EOF [ { - "command": "cc -c -o src/empty.o -Dver=1 src/empty.c", + "command": "cc -c -Dver=1 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } , { - "command": "c++ -c -o src/empty.o -Dver=2 src/empty.c", + "command": "c++ -c -Dver=2 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } , { - "command": "cc -c -o empty.o -Dver=3 empty.c", + "command": "cc -c -Dver=3 empty.c", "directory": "${root_dir}/src", "file": "empty.c" } , { - "command": "c++ -c -o empty.o -Dver=4 empty.c", + "command": "c++ -c -Dver=4 empty.c", "directory": "${root_dir}/src", "file": "empty.c" } diff --git a/tests/functional/cases/intercept/noisy_build.fts b/tests/functional/cases/intercept/intercept/noisy_build.fts similarity index 71% rename from tests/functional/cases/intercept/noisy_build.fts rename to tests/functional/cases/intercept/intercept/noisy_build.fts index a638e99..f6c6f70 100644 --- a/tests/functional/cases/intercept/noisy_build.fts +++ b/tests/functional/cases/intercept/intercept/noisy_build.fts @@ -27,7 +27,7 @@ mkdir -p "${root_dir}/src" touch "${root_dir}/src/empty.c" build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset @@ -35,29 +35,34 @@ set -o xtrace echo "hi there \"people\"" echo "hi again" +echo "מה שלומך?" +echo "Как дела?" +echo "This line might cause an exception in json load" -"\$CC" -c -o src/empty.o -Dver=1 src/empty.c; -"\$CXX" -c -o src/empty.o -Dver=2 src/empty.c; +\$CC -c -Dver=1 src/empty.c & +\$CXX -c -Dver=2 src/empty.c & bash -c "\ -mkdir -p ./this/that \ -touch ./this/that \ -rm -rf ./this" +mkdir -p ./this/that; \ +touch ./this/that; \ +rm -rf ./this;" + +wait true; EOF chmod +x ${build_file} -cat >> "${root_dir}/expected.json" << EOF +cat > "${root_dir}/expected.json" << EOF [ { - "command": "cc -c -o src/empty.o -Dver=1 src/empty.c", + "command": "cc -c -Dver=1 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } , { - "command": "c++ -c -o src/empty.o -Dver=2 src/empty.c", + "command": "c++ -c -Dver=2 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } diff --git a/tests/functional/cases/intercept/parallel_build.fts b/tests/functional/cases/intercept/intercept/parallel_build.fts similarity index 70% rename from tests/functional/cases/intercept/parallel_build.fts rename to tests/functional/cases/intercept/intercept/parallel_build.fts index 442f808..6045fe7 100644 --- a/tests/functional/cases/intercept/parallel_build.fts +++ b/tests/functional/cases/intercept/intercept/parallel_build.fts @@ -27,19 +27,19 @@ mkdir -p "${root_dir}/src" touch "${root_dir}/src/empty.c" build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset set -o xtrace -"\$CC" -c -o src/empty.o -Dver=1 src/empty.c & -"\$CXX" -c -o src/empty.o -Dver=2 src/empty.c & +\$CC -c -Dver=1 src/empty.c & +\$CXX -c -Dver=2 src/empty.c & cd src -"\$CC" -c -o empty.o -Dver=3 empty.c & -"\$CXX" -c -o empty.o -Dver=4 empty.c & +\$CC -c -Dver=3 empty.c & +\$CXX -c -Dver=4 empty.c & wait @@ -47,28 +47,28 @@ true; EOF chmod +x ${build_file} -cat >> "${root_dir}/expected.json" << EOF +cat > "${root_dir}/expected.json" << EOF [ { - "command": "cc -c -o src/empty.o -Dver=1 src/empty.c", + "command": "cc -c -Dver=1 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } , { - "command": "c++ -c -o src/empty.o -Dver=2 src/empty.c", + "command": "c++ -c -Dver=2 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } , { - "command": "cc -c -o empty.o -Dver=3 empty.c", + "command": "cc -c -Dver=3 empty.c", "directory": "${root_dir}/src", "file": "empty.c" } , { - "command": "c++ -c -o empty.o -Dver=4 empty.c", + "command": "c++ -c -Dver=4 empty.c", "directory": "${root_dir}/src", "file": "empty.c" } diff --git a/tests/functional/cases/intercept/intercept/successful_build.bat b/tests/functional/cases/intercept/intercept/successful_build.bat new file mode 100644 index 0000000..ba1742a --- /dev/null +++ b/tests/functional/cases/intercept/intercept/successful_build.bat @@ -0,0 +1,34 @@ +: RUN: %s %T\successful_build +: RUN: cd %T\successful_build; %{expect} --cdb expected.json --command "cc -c -Dver=1 src\empty.c" --file "src\empty.c" +: RUN: cd %T\successful_build; %{expect} --cdb expected.json --command "c++ -c -Dver=2 src\empty.c" --file "src\empty.c" +: RUN: cd %T\successful_build; %{expect} --cdb expected.json --command "cc -c -Dver=3 src\empty.c" --file "src\empty.c" +: RUN: cd %T\successful_build; %{expect} --cdb expected.json --command "c++ -c -Dver=4 src\empty.c" --file "src\empty.c" +: RUN: cd %T\successful_build; %{intercept-build} --override-compiler --cdb wrapper.json run.bat +: RUN: cd %T\successful_build; %{cdb_diff} wrapper.json expected.json + +set root_dir=%1 + +mkdir "%root_dir%" +mkdir "%root_dir%\src" + +copy /y nul "%root_dir%\src\empty.c" + +echo ^ +%%CC%% -c -Dver=1 src\empty.c ^ + +^ + +%%CXX%% -c -Dver=2 src\empty.c ^ + +^ + +%%CC%% -c -Dver=3 src\empty.c ^ + +^ + +%%CXX%% -c -Dver=4 src\empty.c ^ + +> "%root_dir%\run.bat" + +set output="%root_dir%\expected.json" +del /f %output% \ No newline at end of file diff --git a/tests/functional/cases/intercept/successful_build.fts b/tests/functional/cases/intercept/intercept/successful_build.fts similarity index 70% rename from tests/functional/cases/intercept/successful_build.fts rename to tests/functional/cases/intercept/intercept/successful_build.fts index b361d34..00e6c33 100644 --- a/tests/functional/cases/intercept/successful_build.fts +++ b/tests/functional/cases/intercept/intercept/successful_build.fts @@ -27,45 +27,45 @@ mkdir -p "${root_dir}/src" touch "${root_dir}/src/empty.c" build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset set -o xtrace -"\$CC" -c -o src/empty.o -Dver=1 src/empty.c; -"\$CXX" -c -o src/empty.o -Dver=2 src/empty.c; +\$CC -c -Dver=1 src/empty.c; +\$CXX -c -Dver=2 src/empty.c; cd src -"\$CC" -c -o empty.o -Dver=3 empty.c; -"\$CXX" -c -o empty.o -Dver=4 empty.c; +\$CC -c -Dver=3 empty.c; +\$CXX -c -Dver=4 empty.c; true; EOF chmod +x ${build_file} -cat >> "${root_dir}/expected.json" << EOF +cat > "${root_dir}/expected.json" << EOF [ { - "command": "cc -c -o src/empty.o -Dver=1 src/empty.c", + "command": "cc -c -Dver=1 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } , { - "command": "c++ -c -o src/empty.o -Dver=2 src/empty.c", + "command": "c++ -c -Dver=2 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } , { - "command": "cc -c -o empty.o -Dver=3 empty.c", + "command": "cc -c -Dver=3 empty.c", "directory": "${root_dir}/src", "file": "empty.c" } , { - "command": "c++ -c -o empty.o -Dver=4 empty.c", + "command": "c++ -c -Dver=4 empty.c", "directory": "${root_dir}/src", "file": "empty.c" } diff --git a/tests/functional/cases/intercept/intercept/unkown_compiler_recognised.fts b/tests/functional/cases/intercept/intercept/unkown_compiler_recognised.fts new file mode 100644 index 0000000..82834d7 --- /dev/null +++ b/tests/functional/cases/intercept/intercept/unkown_compiler_recognised.fts @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +# RUN: bash %s %T/unkown_compiler_recognised +# RUN: cd %T/unkown_compiler_recognised; %{intercept-build} --use-cc=%T/unkown_compiler_recognised/wrapper --use-c++=%T/unkown_compiler_recognised/wrapper++ --cdb wrapper.json --override-compiler ./run.sh +# RUN: cd %T/unkown_compiler_recognised; %{cdb_diff} wrapper.json expected.json + +set -o errexit +set -o nounset +set -o xtrace + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── wrapper +# ├── wrapper++ +# ├── run.sh +# ├── expected.json +# └── src +# └── empty.c + +root_dir=$1 +mkdir -p "${root_dir}/src" + +touch "${root_dir}/src/empty.c" + +wrapper_file="${root_dir}/wrapper" +cat > ${wrapper_file} << EOF +#!/usr/bin/env bash + +true +EOF +chmod +x ${wrapper_file} + +wrapperxx_file="${root_dir}/wrapper++" +cat > ${wrapperxx_file} << EOF +#!/usr/bin/env bash + +true +EOF +chmod +x ${wrapperxx_file} + +build_file="${root_dir}/run.sh" +cat > ${build_file} << EOF +#!/usr/bin/env bash + +set -o nounset +set -o xtrace + +${wrapper_file} -c -Dver=1 src/empty.c; +${wrapperxx_file} -c -Dver=2 src/empty.c; + +cd src +${wrapper_file} -c -Dver=3 empty.c; +${wrapperxx_file} -c -Dver=4 empty.c; +EOF +chmod +x ${build_file} + +cat > "${root_dir}/expected.json" << EOF +[ +{ + "command": "cc -c -Dver=1 src/empty.c", + "directory": "${root_dir}", + "file": "src/empty.c" +} +, +{ + "command": "c++ -c -Dver=2 src/empty.c", + "directory": "${root_dir}", + "file": "src/empty.c" +} +, +{ + "command": "cc -c -Dver=3 empty.c", + "directory": "${root_dir}/src", + "file": "empty.c" +} +, +{ + "command": "c++ -c -Dver=4 empty.c", + "directory": "${root_dir}/src", + "file": "empty.c" +} +] +EOF diff --git a/tests/functional/cases/intercept/result/define_with_quote.fts b/tests/functional/cases/intercept/result/define_with_quote.fts new file mode 100644 index 0000000..edbd0eb --- /dev/null +++ b/tests/functional/cases/intercept/result/define_with_quote.fts @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +# RUN: bash %s %T/define_with_quote +# RUN: cd %T/define_with_quote; %{intercept-build} --cdb wrapper.json --override-compiler ./run.sh +# RUN: cd %T/define_with_quote; %{cdb_diff} wrapper.json expected.json +# +# when library preload disabled, it falls back to use compiler wrapper +# +# RUN: cd %T/define_with_quote; %{intercept-build} --cdb preload.json ./run.sh +# RUN: cd %T/define_with_quote; %{cdb_diff} preload.json expected.json + +set -o errexit +set -o nounset +set -o xtrace + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── run.sh +# ├── expected.json +# └── src +# └── main.cpp + +root_dir=$1 +mkdir -p "${root_dir}/src" + +cat > "${root_dir}/src/main.cpp" << EOF +#include + +EXPORT void foo(void) { + printf("Hello world!\n"); +} + +int main() { + foo(); +} +EOF + + +build_file="${root_dir}/run.sh" +cat > ${build_file} << EOF +#!/usr/bin/env bash + +set -o nounset +set -o xtrace + +\$CXX -DEXPORT="extern \"C\"" -o hello src/main.cpp +EOF +chmod +x ${build_file} + +cat > "${root_dir}/expected.json" << EOF +[ + { + "arguments": ["c++", "-c", "-DEXPORT=extern \"C\"", "-o", "hello", "src/main.cpp"], + "directory": "${root_dir}", + "file": "src/main.cpp" + } +] +EOF diff --git a/tests/functional/cases/intercept/result/define_with_unicode.fts b/tests/functional/cases/intercept/result/define_with_unicode.fts new file mode 100644 index 0000000..b8837fa --- /dev/null +++ b/tests/functional/cases/intercept/result/define_with_unicode.fts @@ -0,0 +1,65 @@ +#!/usr/bin/env bash + +# RUN: bash %s %T/define_with_unicode +# RUN: cd %T/define_with_unicode; %{intercept-build} --cdb wrapper.json --override-compiler ./run.sh +# RUN: cd %T/define_with_unicode; %{cdb_diff} wrapper.json expected.json +# +# when library preload disabled, it falls back to use compiler wrapper +# +# RUN: cd %T/define_with_unicode; %{intercept-build} --cdb preload.json ./run.sh +# RUN: cd %T/define_with_unicode; %{cdb_diff} preload.json expected.json + +set -o errexit +set -o nounset +set -o xtrace + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── run.sh +# ├── expected.json +# └── src +# └── main.c + +root_dir=$1 +mkdir -p "${root_dir}/src" + +cat > "${root_dir}/src/main.c" << EOF +#include + +static char const * const message = "MESSAGE"; + +int main(void) { + printf("%s\n", message); + return 0; +} +EOF + + +build_file="${root_dir}/run.sh" +cat > ${build_file} << EOF +#!/usr/bin/env bash + +set -o nounset +set -o xtrace + +\$CC -DMESSAGE="מה שלומך?" -o hello src/main.c +\$CC -DMESSAGE="Как дела?" -o hello src/main.c +EOF +chmod +x ${build_file} + + +cat > "${root_dir}/expected.json" << EOF +[ + { + "arguments": ["cc", "-c", "-DMESSAGE=\u041a\u0430\u043a \u0434\u0435\u043b\u0430?", "-o", "hello", "src/main.c"], + "directory": "${root_dir}", + "file": "src/main.c" + }, + { + "arguments": ["cc", "-c", "-DMESSAGE=\u05de\u05d4 \u05e9\u05dc\u05d5\u05de\u05da?", "-o", "hello", "src/main.c"], + "directory": "${root_dir}", + "file": "src/main.c" + } +] +EOF diff --git a/tests/functional/cases/intercept/result/directory_path_absolute.fts b/tests/functional/cases/intercept/result/directory_path_absolute.fts new file mode 100644 index 0000000..30e14d3 --- /dev/null +++ b/tests/functional/cases/intercept/result/directory_path_absolute.fts @@ -0,0 +1,87 @@ +#!/usr/bin/env bash + +# RUN: bash %s %T/directory_path_absolute +# RUN: cd %T/directory_path_absolute; %{intercept-build} --cdb preload.json ./run.sh +# RUN: cd %T/directory_path_absolute; %{python} is_dir.py preload.json +# RUN: cd %T/directory_path_absolute; %{python} is_abs.py preload.json + +set -o errexit +set -o nounset +set -o xtrace + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── run.sh +# ├── is_dir.py +# ├── is_abs.py +# └── src +# └── empty.c + +root_dir=$1 +mkdir -p "${root_dir}/src" + +touch "${root_dir}/src/empty.c" + +build_file="${root_dir}/run.sh" +cat > ${build_file} << EOF +#!/usr/bin/env bash + +set -o nounset +set -o xtrace + +\$CC -c -Dver=1 src/empty.c; +\$CXX -c -Dver=2 src/empty.c; + +cd src + +\$CC -c -Dver=1 empty.c; +\$CXX -c -Dver=2 empty.c; +EOF +chmod +x ${build_file} + +cat > "${root_dir}/is_dir.py" << EOF +#!/usr/bin/env python + +import argparse +import json +import sys +import os.path + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('input', type=argparse.FileType('r')) + args = parser.parse_args() + # file is open, parse the json content + input = json.load(args.input) + # just get directory paths + return [os.path.isdir(entry['directory']) for entry in input].count(False) + + +if __name__ == '__main__': + sys.exit(main()) +EOF + +cat > "${root_dir}/is_abs.py" << EOF +#!/usr/bin/env python + +import argparse +import json +import sys +import os.path + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('input', type=argparse.FileType('r')) + args = parser.parse_args() + # file is open, parse the json content + input = json.load(args.input) + # just get directory paths + return [os.path.isabs(entry['directory']) for entry in input].count(False) + + +if __name__ == '__main__': + sys.exit(main()) +EOF diff --git a/tests/functional/cases/intercept/result/duplicate_entries.fts b/tests/functional/cases/intercept/result/duplicate_entries.fts new file mode 100644 index 0000000..a57a207 --- /dev/null +++ b/tests/functional/cases/intercept/result/duplicate_entries.fts @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +# RUN: bash %s %T/duplicate_entries +# RUN: cd %T/duplicate_entries; %{intercept-build} --cdb preload.json ./run.sh +# RUN: cd %T/duplicate_entries; %{cdb_diff} preload.json expected.json + +set -o errexit +set -o nounset +set -o xtrace + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── run.sh +# ├── expected.json +# └── src +# └── empty.c + +root_dir=$1 +mkdir -p "${root_dir}/src" + +touch "${root_dir}/src/empty.c" + +build_file="${root_dir}/run.sh" +cat > ${build_file} << EOF +#!/usr/bin/env bash + +set -o nounset +set -o xtrace + +\$CC -c -Dver=1 src/empty.c; +\$CXX -c -Dver=2 src/empty.c; + +\$CC -c -Dver=1 src/empty.c; +\$CXX -c -Dver=2 src/empty.c; +EOF +chmod +x ${build_file} + +cat > "${root_dir}/expected.json" << EOF +[ +{ + "command": "cc -c -Dver=1 src/empty.c", + "directory": "${root_dir}", + "file": "src/empty.c" +} +, +{ + "command": "c++ -c -Dver=2 src/empty.c", + "directory": "${root_dir}", + "file": "src/empty.c" +} +] +EOF diff --git a/tests/functional/cases/intercept/deal_with_existing_database.fts b/tests/functional/cases/intercept/result/extend_build.fts similarity index 67% rename from tests/functional/cases/intercept/deal_with_existing_database.fts rename to tests/functional/cases/intercept/result/extend_build.fts index e7c87c5..284076c 100644 --- a/tests/functional/cases/intercept/deal_with_existing_database.fts +++ b/tests/functional/cases/intercept/result/extend_build.fts @@ -29,88 +29,88 @@ mkdir -p "${root_dir}/src" touch "${root_dir}/src/empty.c" build_file="${root_dir}/run-one.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset set -o xtrace -"\$CC" -c -o src/empty.o -Dver=1 src/empty.c; -"\$CXX" -c -o src/empty.o -Dver=2 src/empty.c; +\$CC -c -Dver=1 src/empty.c; +\$CXX -c -Dver=2 src/empty.c; true; EOF chmod +x ${build_file} build_file="${root_dir}/run-two.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset set -o xtrace cd src -"\$CC" -c -o empty.o -Dver=3 empty.c; -"\$CXX" -c -o empty.o -Dver=4 empty.c; +\$CC -c -Dver=3 empty.c; +\$CXX -c -Dver=4 empty.c; true; EOF chmod +x ${build_file} -cat >> "${root_dir}/one.json" << EOF +cat > "${root_dir}/one.json" << EOF [ { - "command": "cc -c -o src/empty.o -Dver=1 src/empty.c", + "command": "cc -c -Dver=1 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } , { - "command": "c++ -c -o src/empty.o -Dver=2 src/empty.c", + "command": "c++ -c -Dver=2 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } ] EOF -cat >> "${root_dir}/two.json" << EOF +cat > "${root_dir}/two.json" << EOF [ { - "command": "cc -c -o empty.o -Dver=3 empty.c", + "command": "cc -c -Dver=3 empty.c", "directory": "${root_dir}/src", "file": "empty.c" } , { - "command": "c++ -c -o empty.o -Dver=4 empty.c", + "command": "c++ -c -Dver=4 empty.c", "directory": "${root_dir}/src", "file": "empty.c" } ] EOF -cat >> "${root_dir}/sum.json" << EOF +cat > "${root_dir}/sum.json" << EOF [ { - "command": "cc -c -o src/empty.o -Dver=1 src/empty.c", + "command": "cc -c -Dver=1 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } , { - "command": "c++ -c -o src/empty.o -Dver=2 src/empty.c", + "command": "c++ -c -Dver=2 src/empty.c", "directory": "${root_dir}", "file": "src/empty.c" } , { - "command": "cc -c -o empty.o -Dver=3 empty.c", + "command": "cc -c -Dver=3 empty.c", "directory": "${root_dir}/src", "file": "empty.c" } , { - "command": "c++ -c -o empty.o -Dver=4 empty.c", + "command": "c++ -c -Dver=4 empty.c", "directory": "${root_dir}/src", "file": "empty.c" } diff --git a/tests/functional/cases/intercept/result/file_path_relative.fts b/tests/functional/cases/intercept/result/file_path_relative.fts new file mode 100644 index 0000000..d35f634 --- /dev/null +++ b/tests/functional/cases/intercept/result/file_path_relative.fts @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +# RUN: bash %s %T/file_path_relative +# RUN: cd %T/file_path_relative; %{intercept-build} --cdb preload.json ./run.sh +# RUN: cd %T/file_path_relative; %{python} is_file.py preload.json +# RUN: cd %T/file_path_relative; %{python} is_rel.py preload.json + +set -o errexit +set -o nounset +set -o xtrace + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── run.sh +# ├── is_file.py +# ├── is_rel.py +# └── src +# └── empty.c + +root_dir=$1 +mkdir -p "${root_dir}/src" + +touch "${root_dir}/src/empty.c" + +build_file="${root_dir}/run.sh" +cat > ${build_file} << EOF +#!/usr/bin/env bash + +set -o nounset +set -o xtrace + +\$CC -c -Dver=1 src/empty.c; +\$CXX -c -Dver=2 src/empty.c; + +cd src + +\$CC -c -Dver=1 empty.c; +\$CXX -c -Dver=2 empty.c; +EOF +chmod +x ${build_file} + +cat > "${root_dir}/is_file.py" << EOF +#!/usr/bin/env python + +import argparse +import json +import sys +import os.path + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('input', type=argparse.FileType('r')) + args = parser.parse_args() + # file is open, parse the json content + input = json.load(args.input) + # just get directory paths + return [os.path.isfile(os.path.join(entry['directory'], entry['file'])) \ + for entry in input].count(False) + + +if __name__ == '__main__': + sys.exit(main()) +EOF + +cat > "${root_dir}/is_rel.py" << EOF +#!/usr/bin/env python + +import argparse +import json +import sys +import os.path + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('input', type=argparse.FileType('r')) + args = parser.parse_args() + # file is open, parse the json content + input = json.load(args.input) + # just get directory paths + return [os.path.isabs(entry['file']) for entry in input].count(True) + + +if __name__ == '__main__': + sys.exit(main()) +EOF diff --git a/tests/functional/cases/intercept/flags_filtered.fts b/tests/functional/cases/intercept/result/flags_filtered.fts similarity index 67% rename from tests/functional/cases/intercept/flags_filtered.fts rename to tests/functional/cases/intercept/result/flags_filtered.fts index 0214280..bdb99a7 100644 --- a/tests/functional/cases/intercept/flags_filtered.fts +++ b/tests/functional/cases/intercept/result/flags_filtered.fts @@ -20,13 +20,12 @@ set -o xtrace root_dir=$1 mkdir -p "${root_dir}/src" -cat >> "${root_dir}/src/lib.c" << EOF +cp "${test_input_dir}/main.c" "${root_dir}/src/main.c" + +cat > "${root_dir}/src/lib.c" << EOF int foo() { return 2; } EOF -cat >> "${root_dir}/src/main.c" << EOF -int main() { return 0; } -EOF # set up platform specific linker options @@ -39,7 +38,7 @@ fi build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset @@ -50,36 +49,35 @@ set -o xtrace cd src # non compilation calls shall not be in the result -"\$CC" -### -c main.c 2> /dev/null -"\$CC" -E -o "\$\$.i" main.c -"\$CC" -S -o "\$\$.asm" main.c -"\$CC" -c -o "\$\$.d" -M main.c -"\$CC" -c -o "\$\$.d" -MM main.c +\$CC -### -c main.c 2> /dev/null +\$CC -E -o "\$\$.i" main.c +\$CC -c -o "\$\$.d" -M main.c +\$CC -c -o "\$\$.d" -MM main.c # preprocessor flags shall be filtered -"\$CC" -c -o one.o -fpic -MD -MT target -MF one.d lib.c -"\$CC" -c -o two.o -fpic -MMD -MQ target -MF two.d lib.c +\$CC -c -o one.o -fpic -MD -MT target -MF one.d lib.c +\$CC -c -o two.o -fpic -MMD -MQ target -MF two.d lib.c # linking shall not in the result -"\$CC" ${LD_FLAGS} one.o two.o +\$CC ${LD_FLAGS} one.o two.o # linker flags shall be filtered -"\$CC" -o "${PREFIX}_one" "-l${PREFIX}" -L. main.c -"\$CC" -o "${PREFIX}_two" -l "${PREFIX}" -L . main.c +\$CC -o "${PREFIX}_one" "-l${PREFIX}" -L. main.c +\$CC -o "${PREFIX}_two" -l "${PREFIX}" -L . main.c true; EOF chmod +x ${build_file} -cat >> "${root_dir}/expected.json" << EOF +cat > "${root_dir}/expected.json" << EOF [ { - "command": "cc -c -o one.o -fpic lib.c", + "command": "cc -c -fpic -o one.o lib.c", "directory": "${root_dir}/src", "file": "lib.c" }, { - "command": "cc -c -o two.o -fpic lib.c", + "command": "cc -c -fpic -o two.o lib.c", "directory": "${root_dir}/src", "file": "lib.c" }, diff --git a/tests/functional/cases/intercept/multiple_source_single_command.fts b/tests/functional/cases/intercept/result/multiple_source_build.fts similarity index 89% rename from tests/functional/cases/intercept/multiple_source_single_command.fts rename to tests/functional/cases/intercept/result/multiple_source_build.fts index ef4bddf..b5ee7bb 100644 --- a/tests/functional/cases/intercept/multiple_source_single_command.fts +++ b/tests/functional/cases/intercept/result/multiple_source_build.fts @@ -26,19 +26,19 @@ touch "${root_dir}/src/two.c" cp "${test_input_dir}/main.c" "${root_dir}/src/main.c" build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF +cat > ${build_file} << EOF #!/usr/bin/env bash set -o nounset set -o xtrace -"\$CC" -Dver=1 src/one.c src/two.c src/main.c; +\$CC -Dver=1 src/one.c src/two.c src/main.c; true; EOF chmod +x ${build_file} -cat >> "${root_dir}/expected.json" << EOF +cat > "${root_dir}/expected.json" << EOF [ { "command": "cc -c -Dver=1 src/one.c", diff --git a/tests/functional/cases/intercept/result/output_kept.fts b/tests/functional/cases/intercept/result/output_kept.fts new file mode 100644 index 0000000..734be67 --- /dev/null +++ b/tests/functional/cases/intercept/result/output_kept.fts @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +# RUN: bash %s %T/output_kept +# RUN: cd %T/output_kept; %{intercept-build} --cdb result.json ./run.sh +# RUN: cd %T/output_kept; %{cdb_diff} result.json expected.json + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── run.sh +# ├── expected.json +# └── src +# └── empty.c + +root_dir=$1 +mkdir -p "${root_dir}/src" + +touch "${root_dir}/src/empty.c" + +build_file="${root_dir}/run.sh" +cat > ${build_file} << EOF +#!/usr/bin/env bash + +set -o nounset +set -o xtrace + +\$CC -c -o src/empty.o src/empty.c; +\$CC -c src/empty.c; + +cd src +\$CC -c -o empty.obj empty.c; +\$CC -c empty.c; + +true; +EOF +chmod +x ${build_file} + +cat > "${root_dir}/expected.json" << EOF +[ +{ + "command": "cc -c -o src/empty.o src/empty.c", + "directory": "${root_dir}", + "file": "src/empty.c" +} +, +{ + "command": "cc -c src/empty.c", + "directory": "${root_dir}", + "file": "src/empty.c" +} +, +{ + "command": "cc -c -o empty.obj empty.c", + "directory": "${root_dir}/src", + "file": "empty.c" +} +, +{ + "command": "cc -c empty.c", + "directory": "${root_dir}/src", + "file": "empty.c" +} +] +EOF diff --git a/tests/functional/cases/intercept/successful_build.ftb b/tests/functional/cases/intercept/successful_build.ftb deleted file mode 100644 index bc02bb3..0000000 --- a/tests/functional/cases/intercept/successful_build.ftb +++ /dev/null @@ -1,32 +0,0 @@ -: RUN: %s %T\successful_build -: RUN: cd %T\successful_build; del /f expected.json -: RUN: cd %T\successful_build; %{cdb_expect} --cdb expected.json --command "cc -c -Dver=1 src\empty.c" --file "src\empty.c" -: RUN: cd %T\successful_build; %{cdb_expect} --cdb expected.json --command "c++ -c -Dver=2 src\empty.c" --file "src\empty.c" -: RUN: cd %T\successful_build; %{cdb_expect} --cdb expected.json --command "cc -c -Dver=3 src\empty.c" --file "src\empty.c" -: RUN: cd %T\successful_build; %{cdb_expect} --cdb expected.json --command "c++ -c -Dver=4 src\empty.c" --file "src\empty.c" -: RUN: cd %T\successful_build; %{intercept-build} --override-compiler --cdb wrapper.json run.bat -: RUN: cd %T\successful_build; %{cdb_diff} wrapper.json expected.json - -set root_dir=%1 - -mkdir "%root_dir%" -mkdir "%root_dir%\src" - -copy /y nul "%root_dir%\src\empty.c" - -echo ^ -%%CC%% -c -Dver=1 src\empty.c ^ - -^ - -%%CXX%% -c -Dver=2 src\empty.c ^ - -^ - -%%CC%% -c -Dver=3 src\empty.c ^ - -^ - -%%CXX%% -c -Dver=4 src\empty.c ^ - -> "%root_dir%\run.bat" diff --git a/tests/functional/cases/intercept/wrapper/compiler_name_from_argument.fts b/tests/functional/cases/intercept/wrapper/compiler_name_from_argument.fts deleted file mode 100644 index 4cc586b..0000000 --- a/tests/functional/cases/intercept/wrapper/compiler_name_from_argument.fts +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env bash - -# RUN: bash %s %T -# RUN: cd %T; %{intercept-wrapped-build} --cdb wrapper.json --override-compiler ./run.sh -# RUN: cd %T; %{cdb_diff} wrapper.json expected.json -# -# when library preload disabled, it falls back to use compiler wrapper -# -# RUN: cd %T; %{intercept-wrapped-build} --cdb preload.json ./run.sh -# RUN: cd %T; %{cdb_diff} preload.json expected.json - -set -o errexit -set -o nounset -set -o xtrace - -# the test creates a subdirectory inside output dir. -# -# ${root_dir} -# ├── wrapper -# ├── wrapper++ -# ├── run.sh -# ├── expected.json -# └── src -# └── empty.c - -root_dir=$1 -mkdir -p "${root_dir}/src" - -touch "${root_dir}/src/empty.c" - -wrapper_file="${root_dir}/wrapper" -cat >> ${wrapper_file} << EOF -#!/usr/bin/env bash - -set -o xtrace - -${REAL_CC} \$@ -EOF -chmod +x ${wrapper_file} - -wrapperxx_file="${root_dir}/wrapper++" -cat >> ${wrapperxx_file} << EOF -#!/usr/bin/env bash - -set -o xtrace - -${REAL_CXX} \$@ -EOF -chmod +x ${wrapperxx_file} - -build_file="${root_dir}/run.sh" -cat >> ${build_file} << EOF -#!/usr/bin/env bash - -set -o nounset -set -o xtrace - -"\$CC" -c -o src/empty.o -Dver=1 src/empty.c; -"\$CXX" -c -o src/empty.o -Dver=2 src/empty.c; - -cd src -"\$CC" -c -o empty.o -Dver=3 empty.c; -"\$CXX" -c -o empty.o -Dver=4 empty.c; -EOF -chmod +x ${build_file} - -cat >> "${root_dir}/expected.json" << EOF -[ -{ - "command": "cc -c -o src/empty.o -Dver=1 src/empty.c", - "directory": "${root_dir}", - "file": "src/empty.c" -} -, -{ - "command": "c++ -c -o src/empty.o -Dver=2 src/empty.c", - "directory": "${root_dir}", - "file": "src/empty.c" -} -, -{ - "command": "cc -c -o empty.o -Dver=3 empty.c", - "directory": "${root_dir}/src", - "file": "empty.c" -} -, -{ - "command": "c++ -c -o empty.o -Dver=4 empty.c", - "directory": "${root_dir}/src", - "file": "empty.c" -} -] -EOF diff --git a/tests/functional/cases/intercept/wrapper/lit.local.cfg b/tests/functional/cases/intercept/wrapper/lit.local.cfg deleted file mode 100644 index 2d72579..0000000 --- a/tests/functional/cases/intercept/wrapper/lit.local.cfg +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. - -import os.path -import lit.util - -this_dir = os.path.dirname(__file__) - -wrapper = os.path.join(this_dir, 'Output', 'wrapper') -wrapperpp = os.path.join(this_dir, 'Output', 'wrapper++') - -config.substitutions.append( - ('%{intercept-wrapped-build}', - 'intercept-build --use-cc={0} --use-c++={1} -vvvv'.format(wrapper, wrapperpp))) - -# use compiler wrapper -config.environment['REAL_CC'] = config.environment['CC'] -config.environment['REAL_CXX'] = config.environment['CXX'] -config.environment['CC'] = wrapper -config.environment['CXX'] = wrapperpp diff --git a/tests/functional/cases/report/report_dir_kept.fts b/tests/functional/cases/report/report_dir_kept.fts index 2b1f051..d3afe04 100644 --- a/tests/functional/cases/report/report_dir_kept.fts +++ b/tests/functional/cases/report/report_dir_kept.fts @@ -22,7 +22,7 @@ mkdir -p "${root_dir}/src" cp "${test_input_dir}/div_zero.c" "${root_dir}/src/broken.c" build_file="${root_dir}/run.sh" -cat >> "${build_file}" << EOF +cat > "${build_file}" << EOF #!/usr/bin/env bash set -o nounset @@ -34,7 +34,7 @@ EOF chmod +x "${build_file}" checker_file="${root_dir}/check.sh" -cat >> "${checker_file}" << EOF +cat > "${checker_file}" << EOF #!/usr/bin/env bash set -o errexit diff --git a/tests/functional/cases/report/report_failures.fts b/tests/functional/cases/report/report_failures.fts index 9cdad59..7517303 100644 --- a/tests/functional/cases/report/report_failures.fts +++ b/tests/functional/cases/report/report_failures.fts @@ -28,7 +28,7 @@ mkdir -p "${root_dir}/src" cp "${test_input_dir}/compile_error.c" "${root_dir}/src/broken.c" -cat >> "${root_dir}/input.json" << EOF +cat > "${root_dir}/input.json" << EOF [ { "directory": "${root_dir}", @@ -39,7 +39,7 @@ cat >> "${root_dir}/input.json" << EOF EOF check_one="${root_dir}/check_exists.sh" -cat >> "${check_one}" << EOF +cat > "${check_one}" << EOF #!/usr/bin/env bash set -o errexit @@ -62,7 +62,7 @@ EOF chmod +x "${check_one}" check_two="${root_dir}/check_not_exists.sh" -cat >> "${check_two}" << EOF +cat > "${check_two}" << EOF #!/usr/bin/env bash set -o errexit diff --git a/tests/functional/cases/report/report_file_format.fts b/tests/functional/cases/report/report_file_format.fts index 1c2890b..c937ff0 100644 --- a/tests/functional/cases/report/report_file_format.fts +++ b/tests/functional/cases/report/report_file_format.fts @@ -25,7 +25,7 @@ mkdir -p "${root_dir}/src" cp "${test_input_dir}/div_zero.c" "${root_dir}/src/broken.c" build_file="${root_dir}/run.sh" -cat >> "${build_file}" << EOF +cat > "${build_file}" << EOF #!/usr/bin/env bash set -o nounset @@ -37,7 +37,7 @@ EOF chmod +x "${build_file}" check_one="${root_dir}/check_plist.sh" -cat >> "${check_one}" << EOF +cat > "${check_one}" << EOF #!/usr/bin/env bash set -o errexit @@ -56,7 +56,7 @@ EOF chmod +x "${check_one}" check_two="${root_dir}/check_html.sh" -cat >> "${check_two}" << EOF +cat > "${check_two}" << EOF #!/usr/bin/env bash set -o errexit diff --git a/tests/functional/lit.local.cfg b/tests/functional/lit.local.cfg index 9695ddc..bb2383a 100644 --- a/tests/functional/lit.local.cfg +++ b/tests/functional/lit.local.cfg @@ -14,30 +14,24 @@ tool_dir = os.path.join(this_dir, 'tools') config.environment['test_input_dir'] = os.path.join(this_dir, 'Input') +config.environment['CC'] = 'clang' +config.environment['CXX'] = 'clang++' + # this hack is needed to run the right compiler on travis-ci clang=os.environ.get('TRAVIS_CLANG', 'clang') -clangpp=os.environ.get('TRAVIS_CLANGPP', 'clang++') - -config.environment['CC'] = clang -config.environment['CXX'] = clangpp config.substitutions.append( ('%{analyze-build}', - 'analyze-build --use-analyzer={clang} -vvvv' \ - .format(clang=clang))) + 'analyze-build --use-analyzer={clang} -vvvv'.format(clang=clang))) config.substitutions.append( ('%{scan-build}', - 'scan-build --use-analyzer={clang} --use-cc={cc} --use-c++={cxx} -vvvv' \ - .format(clang=clang, cc=clang, cxx=clangpp))) + 'scan-build --use-analyzer={clang} -vvvv'.format(clang=clang))) config.substitutions.append( ('%{intercept-build}', - 'intercept-build --use-cc={cc} --use-c++={cxx} -vvvv' \ - .format(cc=clang, cxx=clangpp))) + 'intercept-build -vvvv')) config.substitutions.append( ('%{cdb_diff}', - '{python} {cdb_diff}' \ - .format(python=sys.executable, cdb_diff=os.path.join(tool_dir, 'diff.py')))) + '{python} {diff}'.format(python=sys.executable, diff=os.path.join(tool_dir, 'diff.py')))) config.substitutions.append( ('%{expect}', - '{python} {expect}' \ - .format(python=sys.executable, expect=os.path.join(tool_dir, 'expect.py')))) + '{python} {expect}'.format(python=sys.executable, expect=os.path.join(tool_dir, 'expect.py')))) diff --git a/tests/lit.cfg b/tests/lit.cfg index 21085df..beb0659 100644 --- a/tests/lit.cfg +++ b/tests/lit.cfg @@ -47,7 +47,7 @@ if is_available('qmake-qt4'): is_windows = sys.platform in {'win32', 'cygwin'} if is_windows: config.available_features.add('batch') - config.suffixes.append('.ftb') + config.suffixes.append('.bat') config.environment['windows'] = 'True' else: config.available_features.add('shell') diff --git a/tests/run_pep8.ft b/tests/run_pep8.ft index ad36178..c63c08f 100644 --- a/tests/run_pep8.ft +++ b/tests/run_pep8.ft @@ -1,4 +1,5 @@ # REQUIRES: pep8 # RUN: pep8 --show-source --show-pep8 ../libscanbuild # RUN: pep8 --show-source --show-pep8 ../libear -# RUN: pep8 --show-source --show-pep8 . +# RUN: pep8 --show-source --show-pep8 ./unit +# RUN: pep8 --show-source --show-pep8 ./functional/tools