libabigail/tests/test-diff-filter.cc

210 lines
6.0 KiB
C++
Raw Normal View History

Take filtering in account in diff stats & better categorizing * include/abg-comparison.h (diff_category::ACCESS_CHANGE_CATEGORY): Renamed ACCESS_CHANGED_CATEGORY into this. (diff_category::SIZE_OR_OFFSET_CHANGE_CATEGORY): Renamed SIZE_CHANGED_CATEGORY into this. Changed its semantics to incorporate offset changes as well. * src/abg-comparison.cc (struct noop_deleter): Move this up. (represent): Do not report filtered out data members. (report_mem_header): Add a new num_filtered parameter to take filtered-out members in account in members report headers. Adjust. (class_diff::priv::{count_filtered_bases, count_filtered_data_members, count_filtered_member_functions}): New member functions. When a member is filtered, do not report it all. ({enum_diff, class_diff}::report): Adjust. Take filtered members into account in headers. (corpus_diff::priv::apply_filters_and_compute_diff_stats): New member function. (corpus_diff::priv::emit_diff_stats): Renamed emit_corpus_diff_stats into this. Change it to take the stats in parameter. (corpus_diff::report): Adjust to re-use the above. Filter varibles as well. Take the filtered functions & variables in account in the stats. Do not report filtered-out functions & variables at all. * src/abg-comp-filter.cc (type_size_changed, access_changed) (data_member_offset_changed): New predicates. ({harmless, harmful}_filter::visit): Adjust to use the new predicates above. Update the harmful variant for the new SIZE_OR_OFFSET_CHANGE_CATEGORY category. * tools/bidiff.cc (set_diff_context_from_opts): Adjust for the categories name changes. * tests/data/test-diff-filter/test0-report.txt: New test input. * tests/data/test-diff-filter/test0-v0.cc: Likewise. * tests/data/test-diff-filter/test0-v0.o: Likewise. * tests/data/test-diff-filter/test0-v1.cc: Likewise. * tests/data/test-diff-filter/test0-v1.o: Likewise. * tests/test-diff-filter.cc: New test harness. * tests/Makefile.am: Add the new test files above to the distribution. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-03-29 05:44:13 +00:00
// -*- Mode: C++ -*-
//
// Copyright (C) 2013 Red Hat, Inc.
//
// This file is part of the GNU Application Binary Interface Generic
// Analysis and Instrumentation Library (libabigail). This library is
// free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 3, or (at your option) any
// later version.
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Lesser Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this program; see the file COPYING-LGPLV3. If
// not, see <http://www.gnu.org/licenses/>.
// Author: Dodji Seketeli
/// @file
///
/// This program runs a diff between input ELF files containing DWARF
/// debugging information and compares the resulting report with a
/// reference report. If the resulting report is different from the
/// reference report, the test has failed. Note that the comparison
/// is done using the bidiff command line comparison tool.
///
/// The set of input files and reference reports to consider should be
/// present in the source distribution.
#include <string>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include "abg-tools-utils.h"
#include "test-utils.h"
using std::string;
using std::cerr;
/// This is an aggregate that specifies where a test shall get its
/// input from and where it shall write its ouput to.
struct InOutSpec
{
const char* in_elfv0_path;
const char* in_elfv1_path;
const char* bidiff_options;
const char* in_report_path;
const char* out_report_path;
}; // end struct InOutSpec;
InOutSpec in_out_specs[] =
{
{
"data/test-diff-filter/test0-v0.o",
"data/test-diff-filter/test0-v1.o",
"--no-harmless",
"data/test-diff-filter/test0-report.txt",
"output/test-diff-filter/test0-report.txt",
},
{
"data/test-diff-filter/test0-v0.o",
"data/test-diff-filter/test0-v1.o",
"",
"data/test-diff-filter/test01-report.txt",
"output/test-diff-filter/test01-report.txt",
},
{
"data/test-diff-filter/test1-v0.o",
"data/test-diff-filter/test1-v1.o",
"--no-harmless",
"data/test-diff-filter/test1-report.txt",
"output/test-diff-filter/test1-report.txt",
},
{
"data/test-diff-filter/test2-v0.o",
"data/test-diff-filter/test2-v1.o",
"--no-harmless",
"data/test-diff-filter/test2-report.txt",
"output/test-diff-filter/test2-report.txt",
},
Add a COMPATIBLE_TYPE_CHANGE_CATEGORY to bidiff --no-harmless * include/abg-comparison.h (diff_category::COMPATIBLE_TYPE_CHANGE_CATEGORY): New enumerator. (operator|=(diff_category&, diff_category)): New declaration. * include/abg-fwd.h (is_typedef, strip_typedef) (types_are_compatible): New declarations. * include/abg-ir.h (operator==(const decl_base_sptr, const decl_base_sptr)): Added the consts here. (operator==(const type_base_sptr, const type_base_sptr)): New declaration. * src/abg-comp-filter.cc (is_compatible_change): New static function. (harmless_filter::visit): Detect compatible changes and add the sub-tree into the new COMPATIBLE_TYPE_CHANGE_CATEGORY if applicable. Cleanup the logic. * src/abg-comparison.cc (operator|=(diff_category&, diff_category)): Define new function. (operator==(const decl_base_sptr l, const decl_base_sptr r)): Add consts. (operator==(const type_base_sptr l, const type_base_sptr r)): Define new operator. (is_typedef, strip_typedef, types_are_compatible): New function definitions. * tests/data/test-diff-filter/test3-report.txt: New test report reference. * tests/data/test-diff-filter/test3-v0.cc: Source code for new test input. * tests/data/test-diff-filter/test3-v0.o: New test input. * tests/data/test-diff-filter/test3-v1.cc: Source code for new test input. * tests/data/test-diff-filter/test3-v1.o: New test input. * tests/test-diff-filter.cc: Adjust to consume the new tests inputs above. * tools/bidiff.cc: Add the new COMPATIBLE_TYPE_CHANGE_CATEGORY into the --harmless group. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-02 15:23:56 +00:00
{
"data/test-diff-filter/test3-v0.o",
"data/test-diff-filter/test3-v1.o",
"--no-harmless",
"data/test-diff-filter/test3-report.txt",
"output/test-diff-filter/test3-report.txt",
},
Do not hook type diff nodes to a parent A given diff node for a type can be hung off of several contexts: a function parameter type node, another type diff node, etc. For that reason, a type diff node should not have a parent node. Thus, it's should be the job of the context containing the type diff node to propagate its categories to the context nodes. This actually fixes a bug about category propagation. * abg/comparison.cc (var_diff::var_diff): Do not set parent node for the type diff of the var_diff. (var_diff::traverse): Handle category propagation from the type diff node to the var_diff node. (pointer_diff::underlying_type_diff) (reference_diff::underlying_type_diff) (qualified_type_diff::underlying_type_diff, enum_diff::enum_diff) (base_diff::get_underlying_class_diff) (typedef_diff::underlying_type_diff): Do not set the parent node here. ({pointer_diff, reference_diff, qualified_type, enum_diff, class_diff, base_diff, function_decl_diff, typedef_diff}::traverse): Handle category propagation here. * tests/data/test-diff-filter/test4-v0.o: New input binary. * tests/data/test-diff-filter/test4-v0.cc: Source code for the input binary above. * tests/data/test-diff-filter/test4-v1.o: New input binary. * tests/data/test-diff-filter/test4-v1.cc: Source code for the input binary above. * tests/data/test-diff-filter/test4-report.txt: Reference diff report for the input binaries above. * tests/test-diff-filter.cc:: Run bidiff --no-harmless on the binaries above. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-04 12:44:50 +00:00
{
"data/test-diff-filter/test4-v0.o",
"data/test-diff-filter/test4-v1.o",
"--no-harmless",
"data/test-diff-filter/test4-report.txt",
"output/test-diff-filter/test4-report.txt",
},
Categorize through compatible distinct type diffs * src/abg-comparison.cc (report_size_and_alignment_changes): Split this static function out of ... (report_name_size_and_alignment_changes): ... this one. (distinct_diff::report): If the typedef-stripped variants of the diff subjects are of the same kind, display their diff. Otherwise, tell explicitly is the distinct type diff involves a type size change. (distinct_diff::traverse): If the typedef-stripped variants of the diff subjects are of the same kind, traverse that underlying diff sub-tree and propagate the categorizing possibly resulting from that traversal. * tests/data/test-diff-dwarf/test4-v0.o: New test input binary. * tests/data/test-diff-dwarf/test4-v0.cc: Source code for the input binary above. * tests/data/test-diff-dwarf/test4-v1.o: New test input binary. * tests/data/test-diff-dwarf/test4-v1.cc: Source code for the input binary above. * tests/data/test-diff-dwarf/test4-report.txt: Reference report for the difference between the two binaries above. * tests/data/test-diff-filter/test5-v0.o: New test input binary. * tests/data/test-diff-filter/test5-v0.cc: Source code for the input binary above. * tests/data/test-diff-filter/test5-v1.o: New test input binary. * tests/data/test-diff-filter/test5-v1.cc: Source code for the input binary above. * tests/data/test-diff-filter/test5-report.txt: Reference report for the difference between the two binaries above. * tests/test-diff-filter.cc: Adjust to produce a filtered diff for the two input binaries above. * tests/Makefile.am: Adjust to add missing test files to the distribution. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-05 09:59:16 +00:00
{
"data/test-diff-filter/test5-v0.o",
"data/test-diff-filter/test5-v1.o",
"--no-harmless",
"data/test-diff-filter/test5-report.txt",
"output/test-diff-filter/test5-report.txt",
},
{
"data/test-diff-filter/test6-v0.o",
"data/test-diff-filter/test6-v1.o",
"--no-harmless",
"data/test-diff-filter/test6-report.txt",
"output/test-diff-filter/test6-report.txt",
},
{
"data/test-diff-filter/test7-v0.o",
"data/test-diff-filter/test7-v1.o",
"--no-harmless",
"data/test-diff-filter/test7-report.txt",
"output/test-diff-filter/test7-report.txt",
},
Represent a removed+added data member at a given offset as changed * include/abg-fwd.h (get_data_member_offset): Declare new overload for decl_base_sptr. * include/abg-comparison.h (unsigned_decl_base_sptr_map) (unsigned_changed_type_or_decl_map): New typedefs. * src/abg-ir.cc (get_data_member_offset): Define new overload for decl_base_sptr. * src/abg-comparison.cc (diff_kind::subtype_change_kind): New enumerator for a change about a type or sub-type of a member of a structure/enum. (report_mem_header): Handle the new enumerator above. (class_diff::priv::{deleted_dm_by_offset_, inserted_dm_by_offset_, changed_dm_}): New data members. (class_diff::priv::subtype_changed_dm_): Renamed class_diff::priv::changed_data_members_ into this. (class_diff::priv::subtype_changed_dm): Renamed class_diff::priv::data_member_has_changed into this. Adjust. (class_diff::count_filtered_subtype_changed_dm): Renamed count_filtered_data_members into this. Adjust. (class_diff::priv::count_filtered_changed_dm): New member function. (class_diff::lookup_tables_empty): Adjust. (class_diff::ensure_lookup_tables_populated): Adjust. Detect when a data member is deleted and added back to offset N, and be prepared to present that as a change of data member at offset N. (class_diff::report): Adjust. Report data members of a given offset that have changed. * tests/data/test-diff-dwarf/test6-report.txt: New reference report for new test input. * tests/data/test-diff-dwarf/test6-v0.cc: Source code for new test input binary. * tests/data/test-diff-dwarf/test6-v0.o: New test input binary. * tests/data/test-diff-dwarf/test6-v1.cc: Source code for new test input binary. * tests/data/test-diff-dwarf/test6-v1.o: New test input binary. * tests/test-diff-dwarf.cc: Adjust to include the new test inputs above. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-11 14:52:00 +00:00
{
"data/test-diff-filter/test8-v0.o",
"data/test-diff-filter/test8-v1.o",
"--no-harmless",
"data/test-diff-filter/test8-report.txt",
"output/test-diff-filter/test8-report.txt",
},
Filter non-virtual member fns insertions/deletions from class changes * include/abg-fwd.h (member_function_is_virtual): Declare new function. * include/abg-comparison.h (diff_category::{NON_VIRT_MEM_FUN_CHANGE_CATEGORY, VIRTUAL_MEMBER_CHANGE_CATEGORY}): New enumerators. (diff_category::EVERYTHING_CATEGORY): Adjust. (class_diff::{changed, deleted, inserted}_member_fns): Declare new member functions. * src/abg-comp-filter.cc (data_member_added_or_removed): Add missing comments. (has_non_virtual_mem_fn_change): New static predicate function. (harmless_filter::visit): Categorize non-virtual member function changes in a diff into NON_VIRT_MEM_FUN_CHANGE_CATEGORY. * src/abg-comparison.cc (TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY): New macro. (report_mem_header): Count filtered functions for added/deleted functions as well. (class_diff::priv::count_filtered_changed_mem_fns): Renamed priv::count_filtered_member_functions into this. Filter out changes to non-virtual member functions here. (class_diff::priv::count_filtered_{inserted, deleted}_mem_fns): New member functions. (class_diff::{deleted, inserted, changed}_member_fns): Define new member functions. (class_diff::report): Adjust count for filtered inserted/deleted member functions. Do not report NON_VIRT_MEM_FUN_CHANGE_CATEGORY if it's disallowed. (class_diff::traverse): Propagate only VIRTUAL_MEMBER_CHANGE_CATEGORY from member functions to their enclosing class. * src/abg-ir.cc (member_function_is_virtual): Define new functions. * tools/bidiff.cc (set_diff_context_from_opts): Adjust to add NON_VIRT_MEM_FUN_CHANGE_CATEGORY into the harmless group and VIRTUAL_MEMBER_CHANGE_CATEGORY into the harmful one. * tests/data/test-diff-filter/test0-report.txt: New test input. * tests/data/test-diff-filter/test10-report.txt: Likewise. * tests/data/test-diff-filter/test10-v0.cc: Likewise. * tests/data/test-diff-filter/test10-v0.o: Likewise. * tests/data/test-diff-filter/test10-v1.cc: Likewise. * tests/data/test-diff-filter/test10-v1.o: Likewise. * tests/data/test-diff-filter/test11-report.txt: Likewise. * tests/data/test-diff-filter/test11-v0.cc: Likewise. * tests/data/test-diff-filter/test11-v0.o: Likewise. * tests/data/test-diff-filter/test11-v1.cc: Likewise. * tests/data/test-diff-filter/test11-v1.o: Likewise. * tests/data/test-diff-filter/test2-report.txt: Likewise. * tests/data/test-diff-filter/test9-report.txt: Likewise. * tests/data/test-diff-filter/test9-v0.cc: Likewise. * tests/data/test-diff-filter/test9-v0.o: Likewise. * tests/data/test-diff-filter/test9-v1.cc: Likewise. * tests/data/test-diff-filter/test9-v1.o: Likewise. * tests/test-diff-filter.cc: Consume the test input above to run more tests. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-13 21:09:02 +00:00
{
"data/test-diff-filter/test9-v0.o",
"data/test-diff-filter/test9-v1.o",
"--no-harmless",
"data/test-diff-filter/test9-report.txt",
"output/test-diff-filter/test9-report.txt",
},
{
"data/test-diff-filter/test10-v0.o",
"data/test-diff-filter/test10-v1.o",
"--no-harmless",
"data/test-diff-filter/test10-report.txt",
"output/test-diff-filter/test10-report.txt",
},
{
"data/test-diff-filter/test11-v0.o",
"data/test-diff-filter/test11-v1.o",
"--no-harmless",
"data/test-diff-filter/test11-report.txt",
"output/test-diff-filter/test11-report.txt",
},
{
"data/test-diff-filter/test12-v0.o",
"data/test-diff-filter/test12-v1.o",
"--no-harmless",
"data/test-diff-filter/test12-report.txt",
"output/test-diff-filter/test12-report.txt",
},
Take filtering in account in diff stats & better categorizing * include/abg-comparison.h (diff_category::ACCESS_CHANGE_CATEGORY): Renamed ACCESS_CHANGED_CATEGORY into this. (diff_category::SIZE_OR_OFFSET_CHANGE_CATEGORY): Renamed SIZE_CHANGED_CATEGORY into this. Changed its semantics to incorporate offset changes as well. * src/abg-comparison.cc (struct noop_deleter): Move this up. (represent): Do not report filtered out data members. (report_mem_header): Add a new num_filtered parameter to take filtered-out members in account in members report headers. Adjust. (class_diff::priv::{count_filtered_bases, count_filtered_data_members, count_filtered_member_functions}): New member functions. When a member is filtered, do not report it all. ({enum_diff, class_diff}::report): Adjust. Take filtered members into account in headers. (corpus_diff::priv::apply_filters_and_compute_diff_stats): New member function. (corpus_diff::priv::emit_diff_stats): Renamed emit_corpus_diff_stats into this. Change it to take the stats in parameter. (corpus_diff::report): Adjust to re-use the above. Filter varibles as well. Take the filtered functions & variables in account in the stats. Do not report filtered-out functions & variables at all. * src/abg-comp-filter.cc (type_size_changed, access_changed) (data_member_offset_changed): New predicates. ({harmless, harmful}_filter::visit): Adjust to use the new predicates above. Update the harmful variant for the new SIZE_OR_OFFSET_CHANGE_CATEGORY category. * tools/bidiff.cc (set_diff_context_from_opts): Adjust for the categories name changes. * tests/data/test-diff-filter/test0-report.txt: New test input. * tests/data/test-diff-filter/test0-v0.cc: Likewise. * tests/data/test-diff-filter/test0-v0.o: Likewise. * tests/data/test-diff-filter/test0-v1.cc: Likewise. * tests/data/test-diff-filter/test0-v1.o: Likewise. * tests/test-diff-filter.cc: New test harness. * tests/Makefile.am: Add the new test files above to the distribution. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-03-29 05:44:13 +00:00
// This should be the last entry
{NULL, NULL, NULL, NULL, NULL}
};
int
main()
{
using abigail::tests::get_src_dir;
using abigail::tests::get_build_dir;
using abigail::tools::ensure_parent_dir_created;
bool is_ok = true;
string in_elfv0_path, in_elfv1_path,
bidiff_options, bidiff, cmd,
ref_diff_report_path, out_diff_report_path;
for (InOutSpec* s = in_out_specs; s->in_elfv0_path; ++s)
{
in_elfv0_path = get_src_dir() + "/tests/" + s->in_elfv0_path;
in_elfv1_path = get_src_dir() + "/tests/" + s->in_elfv1_path;
bidiff_options = s->bidiff_options;
ref_diff_report_path = get_src_dir() + "/tests/" + s->in_report_path;
out_diff_report_path = get_build_dir() + "/tests/" + s->out_report_path;
if (!ensure_parent_dir_created(out_diff_report_path))
{
cerr << "could not create parent directory for "
<< out_diff_report_path;
is_ok = false;
continue;
}
bidiff = get_build_dir() + "/tools/bidiff";
bidiff += " " + bidiff_options;
cmd = bidiff + " " + in_elfv0_path + " " + in_elfv1_path;
cmd += " > " + out_diff_report_path;
bool bidiff_ok = true;
if (system(cmd.c_str()))
bidiff_ok = false;
if (bidiff_ok)
{
cmd = "diff -u " + ref_diff_report_path
+ " " + out_diff_report_path;
if (system(cmd.c_str()))
is_ok = false;
}
else
is_ok = false;
}
return !is_ok;
}