test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64.deb \
test-diff-pkg/libsigc++-2.0-0v5-dbgsym_2.4.1-1ubuntu2_amd64.ddeb \
test-diff-pkg/libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64.deb \
+test-diff-pkg/dirpkg-0-dir1/dir.abignore \
test-diff-pkg/dirpkg-0-dir1/libobj-v0.so \
-test-diff-pkg/dirpkg-0-dir2/libobj-v0.so \
-test-diff-pkg/dirpkg-0-report-0.txt \
test-diff-pkg/dirpkg-0-dir1/obj-v0.cc \
+test-diff-pkg/dirpkg-0-dir2/libobj-v0.so \
test-diff-pkg/dirpkg-0-dir2/obj-v0.cc \
+test-diff-pkg/dirpkg-0-report-0.txt \
+test-diff-pkg/dirpkg-1-dir1/libobj-v0.so \
+test-diff-pkg/dirpkg-1-dir1/obj-v0.cc \
+test-diff-pkg/dirpkg-1-dir2/dir.abignore \
+test-diff-pkg/dirpkg-1-dir2/libobj-v0.so \
+test-diff-pkg/dirpkg-1-dir2/obj-v0.cc \
+test-diff-pkg/dirpkg-1-report-0.txt \
+test-diff-pkg/dirpkg-1-report-1.txt \
+test-diff-pkg/dirpkg-2-dir1/libobj-v0.so \
+test-diff-pkg/dirpkg-2-dir1/obj-v0.cc \
+test-diff-pkg/dirpkg-2-dir2/.abignore \
+test-diff-pkg/dirpkg-2-dir2/dir.abignore \
+test-diff-pkg/dirpkg-2-dir2/libobj-v0.so \
+test-diff-pkg/dirpkg-2-dir2/obj-v0.cc \
+test-diff-pkg/dirpkg-2-report-0.txt \
+test-diff-pkg/dirpkg-2-report-1.txt \
+test-diff-pkg/dirpkg-3-dir1/libobj-v0.so \
+test-diff-pkg/dirpkg-3-dir1/obj-v0.cc \
+test-diff-pkg/dirpkg-3-dir2/.abignore \
+test-diff-pkg/dirpkg-3-dir2/libobj-v0.so \
+test-diff-pkg/dirpkg-3-dir2/obj-v0.cc \
+test-diff-pkg/dirpkg-3-report-0.txt \
+test-diff-pkg/dirpkg-3-report-1.txt \
+test-diff-pkg/dirpkg-3.suppr \
test-diff-pkg/tarpkg-0-dir1.tar \
test-diff-pkg/tarpkg-0-dir1.ta \
test-diff-pkg/tarpkg-0-dir1.tar.bz2 \
--- /dev/null
+#taken from test5-fn-supprt-0.suppr
+[suppress_function]
+ # suppress change reports for a function which name is 'bar' ...
+ name = bar
--- /dev/null
+// Compile with:
+// g++ -g -shared -o libobj-v0.so obj-v0.cc
+
+struct S
+{
+ int mem0;
+
+ S()
+ : mem0()
+ {}
+};
+
+void
+bar(S&)
+{}
--- /dev/null
+#taken from test5-fn-supprt-0.suppr
+[suppress_function]
+ # suppress change reports for a function which name is 'bar' ...
+ name = bar
--- /dev/null
+// Compile with:
+// g++ -g -shared -o libobj-v0.so obj-v0.cc
+
+struct S
+{
+ int mem0;
+ char mem1;
+
+ S()
+ : mem0(),
+ mem1()
+ {}
+};
+
+void
+bar(S&)
+{}
--- /dev/null
+================ changes of 'libobj-v0.so'===============
+ Functions changes summary: 0 Removed, 1 Changed, 0 Added function
+ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+ 1 function with some indirect sub-type change:
+
+ [C]'function void bar(S&)' has some indirect sub-type changes:
+ parameter 1 of type 'S&' has sub-type changes:
+ in referenced type 'struct S':
+ type size changed from 32 to 64 bits
+ 1 data member insertion:
+ 'char S::mem1', at offset 32 (in bits)
+
+
+================ end of changes of 'libobj-v0.so'===============
+
--- /dev/null
+// Compile with:
+// g++ -g -shared -o libobj-v0.so obj-v0.cc
+
+struct S0
+{
+ int mem0;
+
+ S0()
+ : mem0()
+ {}
+};
+
+struct S1
+{
+};
+void
+bar(S0&)
+{}
+
+void
+foo(S1&)
+{}
--- /dev/null
+[suppress_function]
+ name = foo
--- /dev/null
+[suppress_function]
+ name = bar
--- /dev/null
+// Compile with:
+// g++ -g -shared -o libobj-v0.so obj-v0.cc
+
+struct S0
+{
+ int mem0;
+ char mem1;
+
+ S0()
+ : mem0(),
+ mem1()
+ {}
+};
+
+struct S1
+{
+ int mem2;
+};
+void
+bar(S0&)
+{}
+
+void
+foo(S1&)
+{}
--- /dev/null
+================ changes of 'libobj-v0.so'===============
+ Functions changes summary: 0 Removed, 1 Changed, 0 Added function
+ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+ 1 function with some indirect sub-type change:
+
+ [C]'function void bar(S&)' has some indirect sub-type changes:
+ parameter 1 of type 'S&' has sub-type changes:
+ in referenced type 'struct S':
+ type size changed from 32 to 64 bits
+ 1 data member insertion:
+ 'char S::mem1', at offset 32 (in bits)
+
+
+================ end of changes of 'libobj-v0.so'===============
+
--- /dev/null
+// Compile with:
+// g++ -g -shared -o libobj-v0.so obj-v0.cc
+
+struct S0
+{
+ int mem0;
+
+ S0()
+ : mem0()
+ {}
+};
+
+struct S1
+{
+};
+void
+bar(S0&)
+{}
+
+void
+foo(S1&)
+{}
--- /dev/null
+[suppress_function]
+ name = foo
--- /dev/null
+// Compile with:
+// g++ -g -shared -o libobj-v0.so obj-v0.cc
+
+struct S0
+{
+ int mem0;
+ char mem1;
+
+ S0()
+ : mem0(),
+ mem1()
+ {}
+};
+
+struct S1
+{
+ int mem2;
+};
+void
+bar(S0&)
+{}
+
+void
+foo(S1&)
+{}
--- /dev/null
+================ changes of 'libobj-v0.so'===============
+ Functions changes summary: 0 Removed, 1 Changed (1 filtered out), 0 Added function
+ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+ 1 function with some indirect sub-type change:
+
+ [C]'function void foo(S1&)' has some indirect sub-type changes:
+ parameter 1 of type 'S1&' has sub-type changes:
+ in referenced type 'struct S1':
+ type size changed from 8 to 32 bits
+ 1 data member insertion:
+ 'int S1::mem2', at offset 0 (in bits)
+
+
+================ end of changes of 'libobj-v0.so'===============
+
--- /dev/null
+[suppress_function]
+ name = bar
using std::string;
using std::cerr;
+using abigail::tests::get_src_dir;
struct InOutSpec
{
const char* first_in_package_path;
const char* second_in_package_path;
const char* prog_options;
+ const char* suppression_path;
const char* first_in_debug_package_path;
const char* second_in_debug_package_path;
const char* ref_report_path;
static InOutSpec in_out_specs[] =
{
+ // dir1 contains a suppr spec - it should be ignored.
{
"data/test-diff-pkg/dirpkg-0-dir1",
"data/test-diff-pkg/dirpkg-0-dir2",
"",
"",
"",
+ "",
"data/test-diff-pkg/dirpkg-0-report-0.txt",
"output/test-diff-pkg/dirpkg-0-report-0.txt"
},
+ // dir2 contains a suppr spec - it should be recognized.
+ {
+ "data/test-diff-pkg/dirpkg-1-dir1",
+ "data/test-diff-pkg/dirpkg-1-dir2",
+ "",
+ "",
+ "",
+ "",
+ "data/test-diff-pkg/dirpkg-1-report-0.txt",
+ "output/test-diff-pkg/dirpkg-1-report-0.txt"
+ },
+ // dir2 contains a suppr spec but --no-abignore is specified,
+ // the file should be ignored.
+ {
+ "data/test-diff-pkg/dirpkg-1-dir1",
+ "data/test-diff-pkg/dirpkg-1-dir2",
+ "--no-abignore",
+ "",
+ "",
+ "",
+ "data/test-diff-pkg/dirpkg-1-report-1.txt",
+ "output/test-diff-pkg/dirpkg-1-report-1.txt"
+ },
+ // dir2 contains several suppr spec files, ".abignore" and
+ // "dir.abignore", so the specs should be merged.
+ {
+ "data/test-diff-pkg/dirpkg-2-dir1",
+ "data/test-diff-pkg/dirpkg-2-dir2",
+ "",
+ "",
+ "",
+ "",
+ "data/test-diff-pkg/dirpkg-2-report-0.txt",
+ "output/test-diff-pkg/dirpkg-2-report-0.txt"
+ },
+ // dir2 contains a suppr spec file, ".abignore" and
+ // an additional suppr file is specified on the command line,
+ // so the specs should be merged.
+ {
+ "data/test-diff-pkg/dirpkg-3-dir1",
+ "data/test-diff-pkg/dirpkg-3-dir2",
+ "",
+ "data/test-diff-pkg/dirpkg-3.suppr",
+ "",
+ "",
+ "data/test-diff-pkg/dirpkg-3-report-0.txt",
+ "output/test-diff-pkg/dirpkg-3-report-0.txt"
+ },
+ // dir2 contains a suppr spec file, ".abignore", which should
+ // be ignored because of the program options and
+ // an additional suppr file is specified on the command line,
+ // which should be recognized.
+ {
+ "data/test-diff-pkg/dirpkg-3-dir1",
+ "data/test-diff-pkg/dirpkg-3-dir2",
+ "--no-abignore",
+ "data/test-diff-pkg/dirpkg-3.suppr",
+ "",
+ "",
+ "data/test-diff-pkg/dirpkg-3-report-1.txt",
+ "output/test-diff-pkg/dirpkg-3-report-1.txt"
+ },
#if WITH_TAR
{
"",
"",
"",
+ "",
"data/test-diff-pkg/tarpkg-0-report-0.txt",
"output/test-diff-pkg/tarpkg-0-report-0.txt"
},
"",
"",
"",
+ "",
"data/test-diff-pkg/tarpkg-0-report-0.txt",
"output/test-diff-pkg/tarpkg-0-report-0.txt"
},
"",
"",
"",
+ "",
"data/test-diff-pkg/tarpkg-0-report-0.txt",
"output/test-diff-pkg/tarpkg-0-report-0.txt"
},
"",
"",
"",
+ "",
"data/test-diff-pkg/tarpkg-0-report-0.txt",
"output/test-diff-pkg/tarpkg-0-report-0.txt"
},
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
"",
+ "",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
"data/test-diff-pkg/test-rpm-report-0.txt",
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
"",
+ "",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"",
"data/test-diff-pkg/test-rpm-report-1.txt",
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
"",
"",
+ "",
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
"data/test-diff-pkg/test-rpm-report-2.txt",
"output/test-diff-pkg/test-rpm-report-2.txt"
"",
"",
"",
+ "",
"data/test-diff-pkg/test-rpm-report-3.txt",
"output/test-diff-pkg/test-rpm-report-3.txt"
},
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"",
+ "",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/test-rpm-report-4.txt",
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
"--no-added-syms",
+ "",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
"data/test-diff-pkg/test-rpm-report-5.txt",
"data/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64.deb",
"data/test-diff-pkg/libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64.deb",
"--fail-no-dbg",
+ "",
"data/test-diff-pkg/libsigc++-2.0-0c2a-dbgsym_2.4.0-1_amd64.ddeb",
"data/test-diff-pkg/libsigc++-2.0-0v5-dbgsym_2.4.1-1ubuntu2_amd64.ddeb",
"data/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64--libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64-report-0.txt",
},
#endif // WITH_DEB
// This should be the last entry.
- {0, 0, 0, 0, 0, 0, 0}
+ {0, 0, 0, 0, 0, 0, 0, 0}
};
int
main()
{
- using abigail::tests::get_src_dir;
using abigail::tests::get_build_dir;
using abigail::tools_utils::ensure_parent_dir_created;
string first_in_package_path, second_in_package_path,
prog_options,
ref_abi_diff_report_path, out_abi_diff_report_path, cmd, abipkgdiff,
- first_in_debug_package_path, second_in_debug_package_path;
+ first_in_debug_package_path, second_in_debug_package_path,
+ suppression_path;
for (InOutSpec *s = in_out_specs; s->first_in_package_path; ++s)
{
first_in_package_path =
get_src_dir() + "/tests/" + s->second_in_debug_package_path;
else
second_in_debug_package_path.clear();
+
+ if (s->suppression_path
+ && strcmp(s->suppression_path, ""))
+ suppression_path =
+ get_src_dir() + "/tests/" + s->suppression_path;
+ else
+ suppression_path.clear();
+
ref_abi_diff_report_path = get_src_dir() + "/tests/" + s->ref_report_path;
out_abi_diff_report_path =
get_build_dir() + "/tests/" + s->out_report_path;
if (!second_in_debug_package_path.empty())
abipkgdiff += " --d2 " + second_in_debug_package_path;
+ if (!suppression_path.empty())
+ abipkgdiff += " --suppressions " + suppression_path;
+
cmd =
abipkgdiff + " " + first_in_package_path + " " + second_in_package_path;
cmd += " > " + out_abi_diff_report_path;
using std::map;
using std::tr1::shared_ptr;
using abigail::tools_utils::guess_file_type;
+using abigail::tools_utils::string_ends_with;
using abigail::tools_utils::file_type;
using abigail::tools_utils::make_path_absolute;
using abigail::tools_utils::abidiff_status;
/// This contains the set of files of a given package. It's populated
/// by a worker function that is invoked on each file contained in the
/// package. So this global variable is filled by the
-/// file_tree_walker_callback_fn() function. Its content is relevant
-/// only during the time after which the current package has been
+/// {first,second}_package_tree_walker_callback_fn() functions. Its content
+/// is relevant only during the time after which the current package has been
/// analyzed and before we start analyzing the next package.
static vector<string> elf_file_paths;
+/// This points to the set of options shared by all the routines of the
+/// program.
+static struct options *prog_options;
+
/// The options passed to the current program.
struct options
{
bool display_usage;
bool missing_operand;
+ bool abignore;
string package1;
string package2;
string debug_package1;
options()
: display_usage(),
missing_operand(),
+ abignore(true),
keep_tmp_files(),
compare_dso_only(),
show_linkage_names(true),
/// A convenience typedef for a shared pointer to elf_file.
typedef shared_ptr<elf_file> elf_file_sptr;
+/// A convenience typedef for a pointer to a function type that
+/// the ftw() function accepts.
+typedef int (*ftw_cb_type)(const char *, const struct stat*, int);
+
/// Abstract the result of comparing two packages.
///
/// This contains the the paths of the set of added binaries, removed
}
/// A callback function invoked by the ftw() function while walking
-/// the directory of files extracted from a given package.
+/// the directory of files extracted from the first package.
///
/// @param fpath the path to the file being considered.
///
/// @param stat the stat struct of the file.
static int
-file_tree_walker_callback_fn(const char *fpath,
- const struct stat *,
- int /*flag*/)
+first_package_tree_walker_callback_fn(const char *fpath,
+ const struct stat *,
+ int /*flag*/)
{
struct stat s;
lstat(fpath, &s);
return 0;
}
+/// A callback function invoked by the ftw() function while walking
+/// the directory of files extracted from the second package.
+///
+/// @param fpath the path to the file being considered.
+///
+/// @param stat the stat struct of the file.
+static int
+second_package_tree_walker_callback_fn(const char *fpath,
+ const struct stat *,
+ int /*flag*/)
+{
+ struct stat s;
+ lstat(fpath, &s);
+
+ if (!S_ISLNK(s.st_mode))
+ {
+ if (guess_file_type(fpath) == abigail::tools_utils::FILE_TYPE_ELF)
+ elf_file_paths.push_back(fpath);
+ /// We go through the files of the newer (second) pkg to look for
+ /// suppression specifications, matching the "*.abignore" name pattern.
+ else if (prog_options->abignore && string_ends_with(fpath, ".abignore"))
+ prog_options->suppression_paths.push_back(fpath);
+ }
+ return 0;
+}
/// Update the diff context from the @ref options data structure.
///
/// @param ctxt the diff context to update.
/// @param true upon successful completion, false otherwise.
static bool
create_maps_of_package_content(package& package,
- const options& opts)
+ const options& opts,
+ ftw_cb_type callback)
{
elf_file_paths.clear();
if (verbose)
<< package.extracted_dir_path()
<< " ...";
- if (ftw(package.extracted_dir_path().c_str(),
- file_tree_walker_callback_fn,
- 16))
+ if (ftw(package.extracted_dir_path().c_str(), callback, 16))
{
cerr << "Error while inspecting files in package"
<< package.extracted_dir_path() << "\n";
/// @return true upon successful completion, false otherwise.
static bool
extract_package_and_map_its_content(package& package,
- const options& opts)
+ const options& opts,
+ ftw_cb_type callback)
{
if (!extract_package(package))
return false;
bool result = true;
if (!package.is_debug_info())
- result |= create_maps_of_package_content(package, opts);
+ result |= create_maps_of_package_content(package, opts, callback);
return result;
}
package& second_package,
const options& opts)
{
- if (!extract_package_and_map_its_content(first_package, opts)
- || !extract_package_and_map_its_content(second_package, opts))
+ if (!extract_package_and_map_its_content(first_package, opts,
+ first_package_tree_walker_callback_fn)
+ || !extract_package_and_map_its_content(second_package, opts,
+ second_package_tree_walker_callback_fn))
return false;
if ((first_package.debug_info_package()
opts.fail_if_no_debug_info = true;
else if (!strcmp(argv[i], "--verbose"))
verbose = true;
+ else if (!strcmp(argv[i], "--no-abignore"))
+ opts.abignore = false;
else if (!strcmp(argv[i], "--suppressions")
|| !strcmp(argv[i], "--suppr"))
{
main(int argc, char* argv[])
{
options opts;
+ prog_options = &opts;
vector<package_sptr> packages;
if (!parse_command_line(argc, argv, opts))
{