Add more leaf change reporting.
authorGiuliano Procida <gprocida@google.com>
Fri, 13 Mar 2020 15:34:29 +0000 (15:34 +0000)
committerDodji Seketeli <dodji@redhat.com>
Fri, 13 Mar 2020 16:58:30 +0000 (17:58 +0100)
The leaf-changes-only reporting path does not report on all the same
kinds of differences as the default reporting path does, such as
reporting about changes to variables, even though they can be
considered leaf changs.

    - The addition or removal of any symbol affects the ABI and is
      clearly a leaf change.
    - A change to a variable's declaration may be local rather than
      caused by a type change elsewhere.

This patch adds these missing pieces and reorders some of the existing
leaf reporting, bringing the default and leaf corpus_diff functions
closer to the point where they can be trivially merged or refactored.

This patch also corrects an error in reporting the total number of
leaf changes.

* doc/manuals/abidiff.rst: Update the documentation for
--leaf-changes-only.
* doc/manuals/abipkgdiff.rst: Likewise.
* src/abg-comparison.cc (emit_diff_stats): Exclude non-leaf
changes to variables from the reported total of leaf changes.
* src/abg-default-reporter.cc (report): In the corpus_diff
override, move some code and comments for clarity.
* src/abg-leaf-reporter.cc (report): In the corpus_diff
override, additionally report removed/added/changed variables
and removed/added symbols absent from debug info.
* tests/data/Makefile.am: Add new test case files.
* tests/data/test-abidiff-exit/test-leaf0-report.txt: Update
to include reporting of variable diff (change of type).
* tests/data/test-abidiff-exit/test-leaf1-report.txt: New test
case with added/removed variables/functions and changed
variables (both local and non-local type changes).
* tests/data/test-abidiff-exit/test-leaf1-v0.cc: Ditto.
* tests/data/test-abidiff-exit/test-leaf1-v0.o: Ditto.
* tests/data/test-abidiff-exit/test-leaf1-v1.cc: Ditto.
* tests/data/test-abidiff-exit/test-leaf1-v1.o: Ditto.
* tests/test-abidiff-exit.cc: Run new test case. Supply
--redundant otherwise the test isn't meaningful.

Signed-off-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
13 files changed:
doc/manuals/abidiff.rst
doc/manuals/abipkgdiff.rst
src/abg-comparison.cc
src/abg-default-reporter.cc
src/abg-leaf-reporter.cc
tests/data/Makefile.am
tests/data/test-abidiff-exit/test-leaf0-report.txt
tests/data/test-abidiff-exit/test-leaf1-report.txt [new file with mode: 0644]
tests/data/test-abidiff-exit/test-leaf1-v0.cc [new file with mode: 0644]
tests/data/test-abidiff-exit/test-leaf1-v0.o [new file with mode: 0644]
tests/data/test-abidiff-exit/test-leaf1-v1.cc [new file with mode: 0644]
tests/data/test-abidiff-exit/test-leaf1-v1.o [new file with mode: 0644]
tests/test-abidiff-exit.cc

index 052f7d56b8e0dfaaeb1b8acf32962107e357c83f..8d914db5313da7fff54ccbd3624f07490fd55626 100644 (file)
@@ -388,7 +388,7 @@ Options
     info, like pure ELF properties.
 
   * ``--leaf-changes-only|-l`` only show leaf changes, so don't show
-    impact analysis report.
+    impact analysis report.  This option implies ``--redundant``.
 
     The typical output of abidiff when comparing two binaries looks
     like this ::
index 34503a0544ac419df87c4a775c08b836a9e3d191..2d8e42dff921fb133a8c453017c56871ba0005b9 100644 (file)
@@ -157,7 +157,7 @@ Options
     other package formats.
 
   * ``--leaf-changes-only|-l`` only show leaf changes, so don't show
-    impact analysis report.
+    impact analysis report.  This option implies ``--redundant``
 
     The typical output of ``abipkgdiff`` and ``abidiff`` when
     comparing two binaries, that we shall call ``full impact report``,
index b99cfa7d063d75c0ff09b77329549883472e3c9f..6539ed7a5eb84290f3f05ea5869faaaa54cf1534 100644 (file)
@@ -9841,7 +9841,7 @@ corpus_diff::priv::emit_diff_stats(const diff_stats&      s,
     s.net_num_leaf_func_changes() +
     s.net_num_vars_removed() +
     s.net_num_vars_added() +
-    s.net_num_vars_changed() +
+    s.net_num_leaf_var_changes() +
     s.net_num_leaf_type_changes();
 
   if (!sonames_equal_)
index 2ac93d413edc28aed30482912c7a172eee33b44b..3bfdfbc43ed6ccc58126d9d79af3a17c29ec2932 100644 (file)
@@ -1761,18 +1761,12 @@ void
 default_reporter::report(const corpus_diff& d, ostream& out,
                         const string& indent) const
 {
-  size_t total = 0;
   const corpus_diff::diff_stats &s =
     const_cast<corpus_diff&>(d).
     apply_filters_and_suppressions_before_reporting();
 
   const diff_context_sptr& ctxt = d.context();
 
-  /// Report removed/added/changed functions.
-  total = s.net_num_func_removed() + s.net_num_func_added() +
-    s.net_num_func_changed();
-  const unsigned large_num = 100;
-
   d.priv_->emit_diff_stats(s, out, indent);
   if (ctxt->show_stats_only())
     return;
@@ -1790,6 +1784,11 @@ default_reporter::report(const corpus_diff& d, ostream& out,
        << d.first_corpus()->get_architecture_name() << "' to '"
        << d.second_corpus()->get_architecture_name() << "'\n\n";
 
+  /// Report removed/added/changed functions.
+  size_t total = s.net_num_func_removed() + s.net_num_func_added() +
+    s.net_num_func_changed();
+  const unsigned large_num = 100;
+
   if (ctxt->show_deleted_fns())
     {
       if (s.net_num_func_removed() == 1)
@@ -2249,7 +2248,6 @@ default_reporter::report(const corpus_diff& d, ostream& out,
 
   // Report added/removed/changed types not reacheable from public
   // interfaces.
-
   maybe_report_unreachable_type_changes(d, s, indent, out);
 
   d.priv_->maybe_dump_diff_tree();
index 4b85d8166c3d85ab8a7cd8b30054f887675ff390..cccc1225f204f5a1237cf10c0a2d0bf1bcfa70e9 100644 (file)
@@ -1034,16 +1034,15 @@ leaf_reporter::report(const corpus_diff& d,
   if (!d.has_changes())
     return;
 
-  const diff_context_sptr& ctxt = d.context();
-
   const corpus_diff::diff_stats &s =
     const_cast<corpus_diff&>(d).
     apply_filters_and_suppressions_before_reporting();
 
+  const diff_context_sptr& ctxt = d.context();
+
   d.priv_->emit_diff_stats(s, out, indent);
   if (ctxt->show_stats_only())
     return;
-
   out << "\n";
 
   if (ctxt->show_soname_change()
@@ -1058,6 +1057,7 @@ leaf_reporter::report(const corpus_diff& d,
        << d.first_corpus()->get_architecture_name() << "' to '"
        << d.second_corpus()->get_architecture_name() << "'\n\n";
 
+  /// Report removed/added/changed functions.
   if (ctxt->show_deleted_fns())
     {
       if (s.net_num_func_removed() == 1)
@@ -1104,6 +1104,55 @@ leaf_reporter::report(const corpus_diff& d,
        out << "\n";
     }
 
+  if (ctxt->show_added_fns())
+    {
+      if (s.net_num_func_added() == 1)
+        out << indent << "1 Added function:\n\n";
+      else if (s.net_num_func_added() > 1)
+        out << indent << s.net_num_func_added()
+            << " Added functions:\n\n";
+      bool emitted = false;
+      vector<function_decl*> sorted_added_fns;
+      sort_string_function_ptr_map(d.priv_->added_fns_, sorted_added_fns);
+      for (vector<function_decl*>::const_iterator i = sorted_added_fns.begin();
+           i != sorted_added_fns.end();
+           ++i)
+        {
+          if (d.priv_->added_function_is_suppressed(*i))
+            continue;
+
+          out
+            << indent
+            << "  ";
+          out << "[A] ";
+          out << "'"
+              << (*i)->get_pretty_representation()
+              << "'";
+          if (ctxt->show_linkage_names())
+            {
+              out << "    {";
+              show_linkage_name_and_aliases
+                (out, "", *(*i)->get_symbol(),
+                 d.second_corpus()->get_fun_symbol_map());
+              out << "}";
+            }
+          out << "\n";
+          if (is_member_function(*i) && get_member_function_is_virtual(*i))
+            {
+              class_decl_sptr c =
+                is_class_type(is_method_type((*i)->get_type())->get_class_type());
+              out << indent
+                  << "    "
+                  << "note that this adds a new entry to the vtable of "
+                  << c->get_pretty_representation()
+                  << "\n";
+            }
+          emitted = true;
+        }
+      if (emitted)
+        out << "\n";
+    }
+
   if (ctxt->show_changed_fns())
     {
       // Show changed functions.
@@ -1174,55 +1223,273 @@ leaf_reporter::report(const corpus_diff& d,
        out << "\n";
     }
 
-  if (ctxt->show_added_fns())
+  // Report removed/added/changed variables.
+  if (ctxt->show_deleted_vars())
     {
-      if (s.net_num_func_added() == 1)
-       out << indent << "1 Added function:\n\n";
-      else if (s.net_num_func_added() > 1)
-       out << indent << s.net_num_func_added()
-           << " Added functions:\n\n";
+      if (s.net_num_vars_removed() == 1)
+       out << indent << "1 Removed variable:\n\n";
+      else if (s.net_num_vars_removed() > 1)
+       out << indent << s.net_num_vars_removed()
+           << " Removed variables:\n\n";
+      string n;
       bool emitted = false;
-      vector<function_decl*> sorted_added_fns;
-      sort_string_function_ptr_map(d.priv_->added_fns_, sorted_added_fns);
-      for (vector<function_decl*>::const_iterator i = sorted_added_fns.begin();
-          i != sorted_added_fns.end();
+      vector<var_decl*> sorted_deleted_vars;
+      sort_string_var_ptr_map(d.priv_->deleted_vars_, sorted_deleted_vars);
+      for (vector<var_decl*>::const_iterator i =
+            sorted_deleted_vars.begin();
+          i != sorted_deleted_vars.end();
           ++i)
        {
-         if (d.priv_->added_function_is_suppressed(*i))
+         if (d.priv_->deleted_variable_is_suppressed(*i))
            continue;
 
-         out
-           << indent
-           << "  ";
-         out << "[A] ";
+         n = (*i)->get_pretty_representation();
+
+         out << indent
+             << "  ";
+         out << "[D] ";
          out << "'"
-             << (*i)->get_pretty_representation()
+             << n
              << "'";
          if (ctxt->show_linkage_names())
            {
              out << "    {";
-             show_linkage_name_and_aliases
-               (out, "", *(*i)->get_symbol(),
-                d.second_corpus()->get_fun_symbol_map());
+             show_linkage_name_and_aliases(out, "", *(*i)->get_symbol(),
+                                           d.first_corpus()->get_var_symbol_map());
              out << "}";
            }
          out << "\n";
-         if (is_member_function(*i) && get_member_function_is_virtual(*i))
+         emitted = true;
+       }
+      if (emitted)
+        out << "\n";
+    }
+
+  if (ctxt->show_added_vars())
+    {
+      if (s.net_num_vars_added() == 1)
+       out << indent << "1 Added variable:\n\n";
+      else if (s.net_num_vars_added() > 1)
+       out << indent << s.net_num_vars_added()
+           << " Added variables:\n\n";
+      string n;
+      bool emitted = false;
+      vector<var_decl*> sorted_added_vars;
+      sort_string_var_ptr_map(d.priv_->added_vars_, sorted_added_vars);
+      for (vector<var_decl*>::const_iterator i =
+            sorted_added_vars.begin();
+          i != sorted_added_vars.end();
+          ++i)
+       {
+         if (d.priv_->added_variable_is_suppressed(*i))
+           continue;
+
+         n = (*i)->get_pretty_representation();
+
+         out << indent
+             << "  ";
+         out << "[A] ";
+         out << "'" << n << "'";
+         if (ctxt->show_linkage_names())
            {
-             class_decl_sptr c =
-               is_class_type(is_method_type((*i)->get_type())->get_class_type());
-             out << indent
-                 << "    "
-                 << "note that this adds a new entry to the vtable of "
-                 << c->get_pretty_representation()
-                 << "\n";
+             out << "    {";
+             show_linkage_name_and_aliases(out, "", *(*i)->get_symbol(),
+                                           d.second_corpus()->get_var_symbol_map());
+             out << "}";
            }
+         out << "\n";
          emitted = true;
        }
       if (emitted)
        out << "\n";
     }
 
+  if (ctxt->show_changed_vars())
+    {
+      size_t num_changed = s.net_num_leaf_var_changes();
+      if (num_changed == 1)
+       out << indent << "1 Changed variable:\n\n";
+      else if (num_changed > 1)
+       out << indent << num_changed
+           << " Changed variables:\n\n";
+      string n1, n2;
+      bool emitted = false;
+      for (var_diff_sptrs_type::const_iterator i =
+            d.priv_->sorted_changed_vars_.begin();
+          i != d.priv_->sorted_changed_vars_.end();
+          ++i)
+       {
+         diff_sptr diff = *i;
+
+         if (!diff)
+           continue;
+
+         if (!diff_to_be_reported(diff.get()))
+            continue;
+
+         n1 = diff->first_subject()->get_pretty_representation();
+         n2 = diff->second_subject()->get_pretty_representation();
+
+         out << indent << "  [C] '" << n1 << "' was changed";
+         if (n1 != n2)
+           out << " to '" << n2 << "'";
+         report_loc_info(diff->second_subject(), *ctxt, out);
+         out << ":\n";
+         diff->report(out, indent + "    ");
+         out << "\n";
+          emitted = true;
+       }
+      if (emitted)
+       out << "\n";
+    }
+
+  // Report removed function symbols not referenced by any debug info.
+  if (ctxt->show_symbols_unreferenced_by_debug_info()
+      && d.priv_->deleted_unrefed_fn_syms_.size())
+    {
+      if (s.net_num_removed_func_syms() == 1)
+       out << indent
+           << "1 Removed function symbol not referenced by debug info:\n\n";
+      else if (s.net_num_removed_func_syms() > 0)
+       out << indent
+           << s.net_num_removed_func_syms()
+           << " Removed function symbols not referenced by debug info:\n\n";
+
+      bool emitted = false;
+      vector<elf_symbol_sptr> sorted_deleted_unrefed_fn_syms;
+      sort_string_elf_symbol_map(d.priv_->deleted_unrefed_fn_syms_,
+                                sorted_deleted_unrefed_fn_syms);
+      for (vector<elf_symbol_sptr>::const_iterator i =
+            sorted_deleted_unrefed_fn_syms.begin();
+          i != sorted_deleted_unrefed_fn_syms.end();
+          ++i)
+       {
+         if (d.priv_->deleted_unrefed_fn_sym_is_suppressed((*i).get()))
+           continue;
+
+         out << indent << "  ";
+         out << "[D] ";
+
+         show_linkage_name_and_aliases(out, "", **i,
+                                       d.first_corpus()->get_fun_symbol_map());
+         out << "\n";
+          emitted = true;
+       }
+      if (emitted)
+       out << "\n";
+    }
+
+  // Report added function symbols not referenced by any debug info.
+  if (ctxt->show_symbols_unreferenced_by_debug_info()
+      && ctxt->show_added_symbols_unreferenced_by_debug_info()
+      && d.priv_->added_unrefed_fn_syms_.size())
+    {
+      if (s.net_num_added_func_syms() == 1)
+       out << indent
+           << "1 Added function symbol not referenced by debug info:\n\n";
+      else if (s.net_num_added_func_syms() > 0)
+       out << indent
+           << s.net_num_added_func_syms()
+           << " Added function symbols not referenced by debug info:\n\n";
+
+      bool emitted = false;
+      vector<elf_symbol_sptr> sorted_added_unrefed_fn_syms;
+      sort_string_elf_symbol_map(d.priv_->added_unrefed_fn_syms_,
+                                sorted_added_unrefed_fn_syms);
+      for (vector<elf_symbol_sptr>::const_iterator i =
+            sorted_added_unrefed_fn_syms.begin();
+          i != sorted_added_unrefed_fn_syms.end();
+          ++i)
+       {
+         if (d.priv_->added_unrefed_fn_sym_is_suppressed((*i).get()))
+           continue;
+
+         out << indent << "  ";
+         out << "[A] ";
+         show_linkage_name_and_aliases(out, "",
+                                       **i,
+                                       d.second_corpus()->get_fun_symbol_map());
+         out << "\n";
+          emitted = true;
+       }
+      if (emitted)
+       out << "\n";
+    }
+
+  // Report removed variable symbols not referenced by any debug info.
+  if (ctxt->show_symbols_unreferenced_by_debug_info()
+      && d.priv_->deleted_unrefed_var_syms_.size())
+    {
+      if (s.net_num_removed_var_syms() == 1)
+       out << indent
+           << "1 Removed variable symbol not referenced by debug info:\n\n";
+      else if (s.net_num_removed_var_syms() > 0)
+       out << indent
+           << s.net_num_removed_var_syms()
+           << " Removed variable symbols not referenced by debug info:\n\n";
+
+      bool emitted = false;
+      vector<elf_symbol_sptr> sorted_deleted_unrefed_var_syms;
+      sort_string_elf_symbol_map(d.priv_->deleted_unrefed_var_syms_,
+                                sorted_deleted_unrefed_var_syms);
+      for (vector<elf_symbol_sptr>::const_iterator i =
+            sorted_deleted_unrefed_var_syms.begin();
+          i != sorted_deleted_unrefed_var_syms.end();
+          ++i)
+       {
+         if (d.priv_->deleted_unrefed_var_sym_is_suppressed((*i).get()))
+           continue;
+
+         out << indent << "  ";
+         out << "[D] ";
+
+         show_linkage_name_and_aliases
+           (out, "", **i,
+            d.first_corpus()->get_fun_symbol_map());
+
+         out << "\n";
+          emitted = true;
+       }
+      if (emitted)
+       out << "\n";
+    }
+
+  // Report added variable symbols not referenced by any debug info.
+  if (ctxt->show_symbols_unreferenced_by_debug_info()
+      && ctxt->show_added_symbols_unreferenced_by_debug_info()
+      && d.priv_->added_unrefed_var_syms_.size())
+    {
+      if (s.net_num_added_var_syms() == 1)
+       out << indent
+           << "1 Added variable symbol not referenced by debug info:\n\n";
+      else if (s.net_num_added_var_syms() > 0)
+       out << indent
+           << s.net_num_added_var_syms()
+           << " Added variable symbols not referenced by debug info:\n\n";
+
+      bool emitted = false;
+      vector<elf_symbol_sptr> sorted_added_unrefed_var_syms;
+      sort_string_elf_symbol_map(d.priv_->added_unrefed_var_syms_,
+                                sorted_added_unrefed_var_syms);
+      for (vector<elf_symbol_sptr>::const_iterator i =
+            sorted_added_unrefed_var_syms.begin();
+          i != sorted_added_unrefed_var_syms.end();
+          ++i)
+       {
+         if (d.priv_->added_unrefed_var_sym_is_suppressed((*i).get()))
+           continue;
+
+         out << indent << "  ";
+         out << "[A] ";
+         show_linkage_name_and_aliases(out, "", **i,
+                                       d.second_corpus()->get_fun_symbol_map());
+         out << "\n";
+          emitted = true;
+       }
+      if (emitted)
+       out << "\n";
+    }
+
   // Now show the changed types.
   const diff_maps& leaf_diffs = d.get_leaf_diffs();
   report_type_changes_from_diff_maps(*this, leaf_diffs, out, indent);
index 0707760873f70d78a6c11bff1bf0c7f1a7b6e949..5dab8685cc2422f56cd3c7c2aeb732fa6ef9f786 100644 (file)
@@ -115,6 +115,11 @@ test-abidiff-exit/test-leaf0-v0.o \
 test-abidiff-exit/test-leaf0-v1.cc \
 test-abidiff-exit/test-leaf0-v1.o \
 test-abidiff-exit/test-leaf0-report.txt \
+test-abidiff-exit/test-leaf1-v0.cc \
+test-abidiff-exit/test-leaf1-v0.o \
+test-abidiff-exit/test-leaf1-v1.cc \
+test-abidiff-exit/test-leaf1-v1.o \
+test-abidiff-exit/test-leaf1-report.txt \
 \
 test-diff-dwarf/test0-v0.cc            \
 test-diff-dwarf/test0-v0.o                     \
index f823789df505f6f8acd072b439a6830f76613d1c..7d15e28f760c0da9532c58a09aaa1efaa8d4334e 100644 (file)
@@ -11,3 +11,12 @@ Removed/Changed/Added variables summary: 0 Removed, 1 Changed, 0 Added variable
       type size changed from 32 to 64 (in bits)
 
 
+1 Changed variable:
+
+  [C] 'int changed_var' was changed to 'long int changed_var':
+    size of symbol changed from 4 to 8
+    type of variable changed:
+     type name changed from 'int' to 'long int'
+     type size changed from 32 to 64 (in bits)
+
+
diff --git a/tests/data/test-abidiff-exit/test-leaf1-report.txt b/tests/data/test-abidiff-exit/test-leaf1-report.txt
new file mode 100644 (file)
index 0000000..b51bb4b
--- /dev/null
@@ -0,0 +1,46 @@
+Leaf changes summary: 7 artifacts changed
+Changed leaf types summary: 1 leaf type changed
+Removed/Changed/Added functions summary: 1 Removed, 1 Changed, 1 Added function
+Removed/Changed/Added variables summary: 1 Removed, 1 Changed, 1 Added variable
+
+1 Removed function:
+
+  [D] 'function int deleted_fun()'    {_Z11deleted_funv}
+
+1 Added function:
+
+  [A] 'function long int added_fun()'    {_Z9added_funv}
+
+1 function with some sub-type change:
+
+  [C] 'function int directly_changed_fun()' has some sub-type changes:
+    return type changed:
+      type name changed from 'int' to 'long int'
+      type size changed from 32 to 64 (in bits)
+
+
+1 Removed variable:
+
+  [D] 'int deleted_var'    {deleted_var}
+
+1 Added variable:
+
+  [A] 'long int added_var'    {added_var}
+
+1 Changed variable:
+
+  [C] 'int directly_changed_var' was changed to 'long int directly_changed_var':
+    size of symbol changed from 4 to 8
+    type of variable changed:
+     type name changed from 'int' to 'long int'
+     type size changed from 32 to 64 (in bits)
+
+
+'struct changed' changed:
+  type size changed from 32 to 64 (in bits)
+  there are data member changes:
+   type 'int' of 'changed::foo' changed:
+     type name changed from 'int' to 'long int'
+     type size changed from 32 to 64 (in bits)
+   and size changed from 32 to 64 (in bits) (by +32 bits)
+
diff --git a/tests/data/test-abidiff-exit/test-leaf1-v0.cc b/tests/data/test-abidiff-exit/test-leaf1-v0.cc
new file mode 100644 (file)
index 0000000..bb6505c
--- /dev/null
@@ -0,0 +1,16 @@
+struct changed {
+  int foo = 0;
+};
+
+int deleted_var = 0;
+int directly_changed_var = 0;
+changed * indirectly_changed_var;
+
+int deleted_fun() {
+  return 0;
+}
+int directly_changed_fun() {
+  return 0;
+}
+void indirectly_changed_fun(changed * x) {
+}
diff --git a/tests/data/test-abidiff-exit/test-leaf1-v0.o b/tests/data/test-abidiff-exit/test-leaf1-v0.o
new file mode 100644 (file)
index 0000000..a873448
Binary files /dev/null and b/tests/data/test-abidiff-exit/test-leaf1-v0.o differ
diff --git a/tests/data/test-abidiff-exit/test-leaf1-v1.cc b/tests/data/test-abidiff-exit/test-leaf1-v1.cc
new file mode 100644 (file)
index 0000000..5df5df9
--- /dev/null
@@ -0,0 +1,16 @@
+struct changed {
+  long foo = 0;
+};
+
+long directly_changed_var = 0;
+changed * indirectly_changed_var;
+long added_var = 0;
+
+long directly_changed_fun() {
+  return 0;
+}
+void indirectly_changed_fun(changed * x) {
+}
+long added_fun() {
+  return 0;
+}
diff --git a/tests/data/test-abidiff-exit/test-leaf1-v1.o b/tests/data/test-abidiff-exit/test-leaf1-v1.o
new file mode 100644 (file)
index 0000000..324180c
Binary files /dev/null and b/tests/data/test-abidiff-exit/test-leaf1-v1.o differ
index 5372b3fe6caf19fb82476717da6419c90f79705c..7a334227127c2092b3bcf6feab2fbf27e3928b5a 100644 (file)
@@ -129,6 +129,17 @@ InOutSpec in_out_specs[] =
     "data/test-abidiff-exit/test-leaf0-report.txt",
     "output/test-abidiff-exit/test-leaf0-report.txt"
   },
+  {
+    "data/test-abidiff-exit/test-leaf1-v0.o",
+    "data/test-abidiff-exit/test-leaf1-v1.o",
+    "",
+    // --redundant - pending a bug fix
+    "--no-show-locs --leaf-changes-only --redundant",
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
+    "data/test-abidiff-exit/test-leaf1-report.txt",
+    "output/test-abidiff-exit/test-leaf1-report.txt"
+  },
   {0, 0, 0 ,0,  abigail::tools_utils::ABIDIFF_OK, 0, 0}
 };