2016-06-27 19:33:17 +00:00
|
|
|
#!/usr/bin/python
|
Bug 20180 - Support system-wide suppression specifications
This patch adds support for loading system and user level suppression
specifications for libabigail tools.
At launch time, relevant libabigail tools (abidiff, abipkgdiff
fedabipkgdiff for now) read the default system suppression
specification file, if it's present, from a file which path is the
value of the environment variable
LIBABIGAIL_DEFAULT_SYSTEM_SUPPRESSION_FILE, if set, or from the file
$libdir/libabigail/default.abignore.
Then it reads the user system suppression specification file, if it's
present, from a file which path is the value of the environment
variable LIBABIGAIL_DEFAULT_USER_SUPPRESSION_FILE, if set, or from the
file $HOME/.abignore.
The content of the user system suppression file is merged with the
content of default system suppression file.
That content is also merged with the content of the suppression
specification files that might be provided by the --suppressions
command line option of the invoked tools.
The resulting set of all these suppression specifications is thus used
to filter the ABI change reports that are emitted.
abidiff, abipkgdiff and abipkgdiff gain a --no-default-suppression
option to avoid loading any of these default suppression specification
files.
The patch also installs a default.abignore file into $(pkglibdir).
Note that on x86_64, that directory is /usr/lib64/libabigail. Now we
just need to think about the content of that default.abignore file.
* doc/manuals/abidiff.rst: Document the default suppression
scheme, its interaction with the --supprs option and the new
--no-default option.
* doc/manuals/abipkgdiff.rst: Likewise.
* doc/manuals/fedabipkgdiff.rst: Likewise.
* configure.ac: Generate the tests/runtestdefaultsupprs.py file
from the new tests/runtestdefaultsupprs.py.in template.
* default.abignore: New file.
* Makefile.am: Add it to source distribution.
* src/Makefile.am: Define the ABIGAIL_ROOT_SYSTEM_LIBDIR
preprocessor macro that is set the value of the $libdir autotools
macro.
* include/abg-tools-utils.h: Update copyright years.
(get_system_libdir, get_default_system_suppression_file_path)
(get_default_user_suppression_file_path)
(load_default_system_suppressions)
(load_default_user_suppressions): Declare new functions
* src/abg-tools-utils.cc (get_system_libdir)
(get_default_system_suppression_file_path)
(get_default_user_suppression_file_path)
(load_default_system_suppressions)
(load_default_user_suppressions): Define new functions.
(is_regular_file): Amend this so that it return true for symlinks
to regular files too.
(is_dir): Amend this so that it returns true for symlinks to
directories too.
* tools/abidiff.cc (options::no_default_supprs): New data member.
(options::options): Initialize the new data member.
(display_usage): Display a new help string for the new
--no-default-suppression command line option.
(parse_command_line): Parse this new command line option.
(set_diff_context_from_opts): Load the default suppression
specifications, unless --no-default-suppression or --supprs was
provided.
* tools/abipkgdiff.cc (options::no_default_supprs): New data
member.
(options::options): Initialize the new data member.
(parse_command_line): Parse the new --no-default-suppression
command line option.
(main): Load the default suppression specifications, unless
--no-default-suppression or --supprs was provided.
* tools/fedabipkgdiff (abipkgdiff): Add --no-default-suppression
to the invocation of abipkgdiff if it was provided on the command
line.
(build_commandline_args_parser): Parse the new
--no-default-suppression command line option.
* tests/runtestdefaultsupprs.py.in: New test harness template.
* tests/Makefile.am: Add the new runtestdefaultsupprs.py to the
set of tests.
* tests/data/test-default-supprs/test0-type-suppr-0.suppr: New
test input.
* tests/data/test-default-supprs/test0-type-suppr-report-0.txt: Likewise.
* tests/data/test-default-supprs/test0-type-suppr-v0.o: Likewise.
* tests/data/test-default-supprs/test0-type-suppr-v1.o: Likewise.
* tests/data/test-default-supprs/dirpkg-1-dir-report-0.txt:
Likewise.
* tests/data/test-default-supprs/dirpkg-1-dir1: Likewise.
* tests/data/test-default-supprs/dirpkg-1-dir2: Likewise.
* tests/data/Makefile.am: Add new the new tests input above to
Makefile.am.
* tests/runtestcanonicalizetypes.sh.in: Pass
--no-default-suppression to abidiff invocations.
* tests/runtestdefaultsupprs.py.in: Likewise.
* tests/test-abidiff-exit.cc: Likewise.
* tests/test-diff-dwarf-abixml.cc: Likewise.
* tests/test-diff-filter.cc: Likewise.
* tests/test-diff-suppr.cc: Likewise.
* tools/abidiff.cc: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2016-05-30 08:37:48 +00:00
|
|
|
|
|
|
|
'''Runs tests for the default suppression specifications of libabigail.
|
|
|
|
|
|
|
|
This program tries to exercise the reading of default suppression
|
|
|
|
files by the abidiff and abipkgdiff programs.
|
|
|
|
|
|
|
|
It reads a set of input files to ABI-compare, along with a
|
|
|
|
suppressions specification and a reference output. The test points
|
|
|
|
the environment variables LIBABIGAIL_DEFAULT_SYSTEM_SUPPRESSION_FILE
|
|
|
|
and LIBABIGAIL_USER_SYSTEM_SUPPRESSION_FILE environment variables at
|
|
|
|
the suppression specification and runs abidiff to compare the two
|
|
|
|
input binary files. The result of the comparison should be equal to
|
|
|
|
the reference output, meaning that the suppression specification was
|
|
|
|
taken into account.
|
|
|
|
'''
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
|
|
|
|
abidiff = '@top_builddir@/tools/abidiff'
|
|
|
|
abipkgdiff = '@top_builddir@/tools/abipkgdiff'
|
|
|
|
test_src_dir = '@top_srcdir@/tests'
|
|
|
|
test_build_dir = '@top_builddir@/tests'
|
|
|
|
input_dir = '@top_srcdir@/tests/data/test-default-supprs'
|
|
|
|
output_dir = '@top_builddir@/tests/output/test-default-supprs'
|
|
|
|
|
|
|
|
# This variable named is a list of 5-uples. Here is the meaning of
|
|
|
|
# the elements of each 5-uples:
|
|
|
|
#
|
|
|
|
# (first binary to compare,
|
|
|
|
# second binary to compare,
|
|
|
|
# suppression specification,
|
|
|
|
# reference output file,
|
|
|
|
# where to store the result of the comparison)
|
|
|
|
#
|
|
|
|
abidiff_test_specs = [('data/test-default-supprs/test0-type-suppr-v0.o',
|
|
|
|
'data/test-default-supprs/test0-type-suppr-v1.o',
|
|
|
|
'data/test-default-supprs/test0-type-suppr-0.suppr',
|
|
|
|
'data/test-default-supprs/test0-type-suppr-report-0.txt',
|
|
|
|
'output/test-default-supprs/test0-type-suppr-report-0.txt'),]
|
|
|
|
|
|
|
|
# This variable named is a list of 5-uples. Here is the meaning of
|
|
|
|
# the elements of each 5-uples:
|
|
|
|
#
|
|
|
|
# (first package to compare,
|
|
|
|
# second package to compare,
|
|
|
|
# suppression specification,
|
|
|
|
# reference output file,
|
|
|
|
# where to store the result of the comparison)
|
|
|
|
#
|
|
|
|
abipkgdiff_test_specs = [('data/test-default-supprs/dirpkg-1-dir1',
|
|
|
|
'data/test-default-supprs/dirpkg-1-dir2',
|
|
|
|
'data/test-default-supprs/dirpkg-1-dir2/dir.abignore',
|
|
|
|
'data/test-default-supprs/dirpkg-1-dir-report-0.txt',
|
|
|
|
'output/test-default-supprs/dirpkg-1-dir-report-0.txt')]
|
|
|
|
|
|
|
|
|
|
|
|
def ensure_output_dir_created():
|
|
|
|
'''Create output dir if it's not already created.'''
|
|
|
|
|
|
|
|
try:
|
|
|
|
os.makedirs(output_dir)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if not os.path.exists(output_dir):
|
|
|
|
sys.exit(1);
|
|
|
|
|
|
|
|
def run_abidiff_tests():
|
|
|
|
"""Run the abidiff default suppression tests.
|
|
|
|
|
|
|
|
Loop through the test inputs in the abidiff_test_specs global
|
|
|
|
variable and for each of the test input, launch a comparison using
|
|
|
|
abidiff and setting LIBABIGAIL_SYSTEM_SUPPRESSION_FILE and
|
|
|
|
LIBABIGAIL_USER_SYSTEM_SUPPRESSION_FILE environment variables.
|
|
|
|
|
|
|
|
Note that if LIBABIGAIL_SYSTEM_SUPPRESSION_FILE is not set,
|
|
|
|
libabigail tries to load the file
|
|
|
|
$libdir/libabigail/defaul-libabigail.abignore, and then tries to
|
|
|
|
load the file $HOME/.abignore. This program does not test the
|
|
|
|
case where LIBABIGAIL_SYSTEM_SUPPRESSION_FILE and
|
|
|
|
LIBABIGAIL_USER_SYSTEM_SUPPRESSION_FILE are not set.
|
|
|
|
|
|
|
|
This function returns the exit code of the abidiff program.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
default_suppression = output_dir + "/default.abignore"
|
|
|
|
with open(default_suppression, 'w') as out:
|
|
|
|
out.write('\n');
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
for test_spec in abidiff_test_specs:
|
|
|
|
binary1 = test_spec[0]
|
|
|
|
binary2 = test_spec[1]
|
|
|
|
suppressions = test_spec[2]
|
|
|
|
reference_report_path = test_spec[3]
|
|
|
|
output_path = test_spec[4]
|
|
|
|
|
|
|
|
binary1 = test_src_dir + "/" + binary1
|
|
|
|
binary2 = test_src_dir + "/" + binary2
|
|
|
|
suppressions = test_src_dir + "/" + suppressions if suppressions else ''
|
|
|
|
reference_report_path = test_src_dir + "/" + reference_report_path
|
|
|
|
output_path = test_build_dir + "/" + output_path
|
|
|
|
|
|
|
|
cmd = [abidiff, binary1, binary2]
|
|
|
|
|
|
|
|
# The environment variables that say where to find the default
|
|
|
|
# suppression specifications loaded by libabigail.
|
|
|
|
envs = {
|
|
|
|
'LIBABIGAIL_DEFAULT_SYSTEM_SUPPRESSION_FILE' : default_suppression,
|
|
|
|
'LIBABIGAIL_DEFAULT_USER_SUPPRESSION_FILE' : default_suppression
|
|
|
|
}
|
|
|
|
|
|
|
|
# Initialize the environment variables above to their default
|
|
|
|
# value.
|
|
|
|
for name, value in envs.items():
|
|
|
|
os.environ[name] = value;
|
|
|
|
|
|
|
|
for env_name in envs:
|
|
|
|
env_vars = os.environ
|
|
|
|
if suppressions:
|
|
|
|
env_vars[env_name] = suppressions
|
|
|
|
|
|
|
|
with open(output_path, 'w') as out_file:
|
|
|
|
subprocess.call(cmd, env=env_vars, stdout=out_file)
|
|
|
|
|
|
|
|
diffcmd = ['diff', '-u', reference_report_path,
|
|
|
|
output_path]
|
|
|
|
|
|
|
|
return_code = subprocess.call(diffcmd)
|
|
|
|
if return_code:
|
|
|
|
result = return_code
|
|
|
|
sys.stderr.write("failed abidiff test "
|
|
|
|
"for env var '" + e + "'\n");
|
|
|
|
|
|
|
|
del env_vars[env_name];
|
|
|
|
|
|
|
|
try:
|
|
|
|
os.remove(default_suppression)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
def run_abipkgdiff_tests():
|
|
|
|
"""Run the abipkgdiff default suppression tests.
|
|
|
|
|
|
|
|
Loop through the test inputs in the abipkgdiff_test_specs global
|
|
|
|
variable and for each of the input packages, launch a comparison
|
|
|
|
using abipkgdiff and setting LIBABIGAIL_SYSTEM_SUPPRESSION_FILE
|
|
|
|
and LIBABIGAIL_USER_SYSTEM_SUPPRESSION_FILE environment variables.
|
|
|
|
|
|
|
|
Note that if LIBABIGAIL_SYSTEM_SUPPRESSION_FILE is not set,
|
|
|
|
libabigail tries to load the file
|
|
|
|
$libdir/libabigail/defaul-libabigail.abignore, and then tries to
|
|
|
|
load the file $HOME/.abignore. This program does not test the
|
|
|
|
case where LIBABIGAIL_SYSTEM_SUPPRESSION_FILE and
|
|
|
|
LIBABIGAIL_USER_SYSTEM_SUPPRESSION_FILE are not set.
|
|
|
|
|
|
|
|
This function returns the exit code of the abipkgdiff program.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
default_suppression = output_dir + "/default.abignore"
|
|
|
|
with open(default_suppression, 'w') as out:
|
|
|
|
out.write('\n');
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
for test_spec in abipkgdiff_test_specs:
|
|
|
|
pkg1 = test_spec[0]
|
|
|
|
pkg2 = test_spec[1]
|
|
|
|
suppressions = test_spec[2]
|
|
|
|
reference_report_path = test_spec[3]
|
|
|
|
output_path = test_spec[4]
|
|
|
|
|
|
|
|
pkg1 = test_src_dir + "/" + pkg1
|
|
|
|
pkg2 = test_src_dir + "/" + pkg2
|
|
|
|
suppressions = test_src_dir + "/" + suppressions if suppressions else ''
|
|
|
|
reference_report_path = test_src_dir + "/" + reference_report_path
|
|
|
|
output_path = test_build_dir + "/" + output_path
|
|
|
|
|
|
|
|
cmd = [abipkgdiff, '--no-abignore', pkg1, pkg2]
|
|
|
|
|
|
|
|
# The environment variables that say where to find the default
|
|
|
|
# suppression specifications loaded by libabigail.
|
|
|
|
envs = {
|
|
|
|
'LIBABIGAIL_DEFAULT_SYSTEM_SUPPRESSION_FILE' : default_suppression,
|
|
|
|
'LIBABIGAIL_DEFAULT_USER_SUPPRESSION_FILE' : default_suppression
|
|
|
|
}
|
|
|
|
|
|
|
|
# Initialize the environment variables above to their default
|
|
|
|
# value.
|
|
|
|
for name, value in envs.items():
|
|
|
|
os.environ[name] = value;
|
|
|
|
|
|
|
|
for env_name in envs:
|
|
|
|
env_vars = os.environ
|
|
|
|
if suppressions:
|
|
|
|
env_vars[env_name] = suppressions
|
|
|
|
|
|
|
|
with open(output_path, 'w') as out_file:
|
|
|
|
subprocess.call(cmd, env=env_vars, stdout=out_file)
|
|
|
|
|
|
|
|
diffcmd = ['diff', '-u', reference_report_path,
|
|
|
|
output_path]
|
|
|
|
|
|
|
|
return_code = subprocess.call(diffcmd)
|
|
|
|
if return_code:
|
|
|
|
result = return_code
|
|
|
|
sys.stderr.write("failed abipkgdiff test "
|
|
|
|
"for env var '" + e + "'\n");
|
|
|
|
|
|
|
|
del env_vars[env_name];
|
|
|
|
|
|
|
|
try:
|
|
|
|
os.remove(default_suppression)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
def main():
|
|
|
|
"""The main entry point of this program.
|
|
|
|
|
|
|
|
This creates the output directory and launches the tests for the
|
|
|
|
abidiff and abipkgdiff probrams. It the abidiff programs returns
|
|
|
|
with a non-zero exit code, this function returns that exit code
|
|
|
|
immediatly. Otherwise, it runs the abipkgdiff tests and returns
|
|
|
|
its exit code.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
ensure_output_dir_created()
|
|
|
|
result = 0;
|
|
|
|
result = run_abidiff_tests()
|
|
|
|
if result:
|
|
|
|
return result;
|
|
|
|
result = run_abipkgdiff_tests()
|
|
|
|
return result;
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
exit_code = main()
|
|
|
|
sys.exit(exit_code)
|