]> sourceware.org Git - libabigail.git/commitdiff
Fix corpus_diff::has_net_changes for --leaf-changes-only mode
authorGiuliano Procida <gprocida@google.com>
Fri, 17 Jul 2020 12:01:01 +0000 (14:01 +0200)
committerDodji Seketeli <dodji@redhat.com>
Tue, 21 Jul 2020 06:53:19 +0000 (08:53 +0200)
This function was not aware of --leaf-changes-only mode.

    - Stats counters for changed variables and types have
      different names in the different modes.
    - Net leaf type changes were not included in leaf mode.

For some inputs, this resulted in abidiff producing an empty report
but returning a non-zero exit status in --leaf-changes-only mode.

For other inputs the combination of both issues still resulted in the
correct return code. This included the following test-abidiff-exit
test cases:

    - test-leaf-peeling
    - test-leaf2
    - test-no-stray-comma

This patch makes corpus_diff::has_net_changes mirror emit_diff_stats,
modulo flags like --non-reachable-types which if absent can still
result in discrepancies between output and return code.

To achieve this in a more maintainable way, the patch introduces a new interface
reporter_base::diff_has_net_changes.  That interface is implemented by
all current reporters.  Each reporter focuses on its own
particularities to provide the required behavious. Then
corpus_diff:has_net_changes just has to invoke
reporter_base::diff_has_net_changes on the reporter that is currently
in used.

The tests below verify that the exit code is zero when all the changes
between the test files are suppressed.

* include/abg-reporter.h ({reporter_base, default_reporter,
leaf_reporter}::diff_has_net_changes): Add new virtual function.
This breaks binary compatibility but should conserve source
compatibility.
* src/abg-default-reporter.cc
(default_reporter::diff_has_net_changes): Define new member
function.
* src/abg-leaf-reporter.cc (leaf_reporter::diff_has_net_changes):
Likewise.
* src/abg-comparison.cc (corpus_diff::has_net_changes): Invoke
reporter_base::diff_has_net_changes on the current reporter,
rather than trying to handle all the different kinds of reporters
here.
(corpus_diff::priv::apply_filters_and_compute_diff_stats): Add a
TODO to possibly delegate the implementation of this function to
the reporters.
* tests/data/Makefile.am: Add new test case files.
* tests/data/test-abidiff-exit/test-net-change-report0.txt:
Normal mode, nothing suppressed.
* tests/data/test-abidiff-exit/test-net-change-report1.txt:
Normal mode, everything suppressed.
* tests/data/test-abidiff-exit/test-net-change-report2.txt:
Leaf mode, nothing suppressed.
* tests/data/test-abidiff-exit/test-net-change-report3.txt:
Leaf mode, everything suppressions.
* tests/data/test-abidiff-exit/test-net-change-v0.c: Test file
* tests/data/test-abidiff-exit/test-net-change-v0.o: Test file
* tests/data/test-abidiff-exit/test-net-change-v1.c: Test file
* tests/data/test-abidiff-exit/test-net-change-v1.o: Test file
* tests/data/test-abidiff-exit/test-net-change.abignore: This
suppresses changes for all variables, functions and types in
the test files, except for the 'victim' function.
* tests/test-abidiff-exit.cc: Run new test cases.

Reviewed-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
15 files changed:
include/abg-reporter.h
src/abg-comparison.cc
src/abg-default-reporter.cc
src/abg-leaf-reporter.cc
tests/data/Makefile.am
tests/data/test-abidiff-exit/test-net-change-report0.txt [new file with mode: 0644]
tests/data/test-abidiff-exit/test-net-change-report1.txt [new file with mode: 0644]
tests/data/test-abidiff-exit/test-net-change-report2.txt [new file with mode: 0644]
tests/data/test-abidiff-exit/test-net-change-report3.txt [new file with mode: 0644]
tests/data/test-abidiff-exit/test-net-change-v0.c [new file with mode: 0644]
tests/data/test-abidiff-exit/test-net-change-v0.o [new file with mode: 0644]
tests/data/test-abidiff-exit/test-net-change-v1.c [new file with mode: 0644]
tests/data/test-abidiff-exit/test-net-change-v1.o [new file with mode: 0644]
tests/data/test-abidiff-exit/test-net-change.abignore [new file with mode: 0644]
tests/test-abidiff-exit.cc

index e0d9e66a69a86fa377a8faad78cea256f79d4c12..bf113f059c0f7863f7c90cb8a70211dc8e39bec4 100644 (file)
@@ -73,6 +73,8 @@ public:
 
   virtual bool diff_to_be_reported(const diff *d) const;
 
+  virtual bool diff_has_net_changes(const corpus_diff *d) const = 0;
+
   virtual void
   report(const type_decl_diff& d, std::ostream& out,
         const std::string& indent = "") const = 0;
@@ -162,6 +164,8 @@ class default_reporter : public reporter_base
 {
 public:
 
+  virtual bool diff_has_net_changes(const corpus_diff *d) const;
+
   virtual void
   report(const type_decl_diff& d, std::ostream& out,
         const std::string& indent = "") const;
@@ -266,6 +270,8 @@ public:
 
   virtual bool diff_to_be_reported(const diff *d) const;
 
+  virtual bool diff_has_net_changes(const corpus_diff *d) const;
+
   void
   report_changes_from_diff_maps(const diff_maps&, std::ostream& out,
                                const std::string& indent) const;
index b6f065f237bfe26e14a8a93aca511cd65a746082..a9ef16103b4ade3ac2ec044d72db8e30000584e6 100644 (file)
@@ -10063,6 +10063,9 @@ corpus_diff::priv::apply_filters_and_compute_diff_stats(diff_stats& stat)
 /// Emit the summary of the functions & variables that got
 /// removed/changed/added.
 ///
+/// TODO: This should be handled by the reporters, just like what is
+/// done for reporter_base::diff_to_be_reported.
+///
 /// @param out the output stream to emit the stats to.
 ///
 /// @param indent the indentation string to use in the summary.
@@ -10848,26 +10851,7 @@ corpus_diff::has_net_subtype_changes() const
 /// carries subtype changes that are deemed incompatible ABI changes.
 bool
 corpus_diff::has_net_changes() const
-{
-    const diff_stats& stats = const_cast<corpus_diff*>(this)->
-      apply_filters_and_suppressions_before_reporting();
-
-    return (architecture_changed()
-           || soname_changed()
-           || stats.net_num_func_changed()
-           || stats.net_num_vars_changed()
-           || stats.net_num_func_added()
-           || stats.net_num_added_func_syms()
-           || stats.net_num_func_removed()
-           || stats.net_num_removed_func_syms()
-           || stats.net_num_vars_added()
-           || stats.net_num_added_var_syms()
-           || stats.net_num_vars_removed()
-           || stats.net_num_removed_var_syms()
-           || stats.net_num_added_unreachable_types()
-           || stats.net_num_removed_unreachable_types()
-           || stats.net_num_changed_unreachable_types());
-}
+{return  context()->get_reporter()->diff_has_net_changes(this);}
 
 /// Apply the different filters that are registered to be applied to
 /// the diff tree; that includes the categorization filters.  Also,
index 2948e15612a0bd90da82fa00b7d95a5f9706c8d4..f8572f25cef0e9a84873270eb28f90639b965be5 100644 (file)
@@ -35,6 +35,41 @@ namespace abigail
 namespace comparison
 {
 
+/// Test if a given instance of @ref corpus_diff carries changes whose
+/// reports are not suppressed by any suppression specification.  In
+/// effect, these are deemed incompatible ABI changes.
+///
+/// @param d the @ref corpus_diff to consider
+///
+/// @return true iff @p d carries subtype changes that are deemed
+/// incompatible ABI changes.
+bool
+default_reporter::diff_has_net_changes(const corpus_diff *d) const
+{
+  if (!d)
+    return false;
+
+  const corpus_diff::diff_stats& stats = const_cast<corpus_diff*>(d)->
+    apply_filters_and_suppressions_before_reporting();
+
+  // Logic here should match emit_diff_stats.
+  return (d->architecture_changed()
+         || d->soname_changed()
+         || stats.net_num_func_removed()
+         || stats.net_num_func_changed()
+         || stats.net_num_func_added()
+         || stats.net_num_vars_removed()
+         || stats.net_num_vars_changed()
+         || stats.net_num_vars_added()
+         || stats.net_num_removed_unreachable_types()
+         || stats.net_num_changed_unreachable_types()
+         || stats.net_num_added_unreachable_types()
+         || stats.net_num_removed_func_syms()
+         || stats.net_num_added_func_syms()
+         || stats.net_num_removed_var_syms()
+         || stats.net_num_added_var_syms());
+}
+
 /// Ouputs a report of the differences between of the two type_decl
 /// involved in the @ref type_decl_diff.
 ///
index 783ffbc0d64a694f3cefae9e5b1297b4e273aa4c..0875c968de7e0db0bde68d2f0f636c45a8d2c6e8 100644 (file)
@@ -45,6 +45,42 @@ bool
 leaf_reporter::diff_to_be_reported(const diff *d) const
 {return d && d->to_be_reported() && d->has_local_changes();}
 
+/// Test if a given instance of @ref corpus_diff carries changes whose
+/// reports are not suppressed by any suppression specification.  In
+/// effect, these are deemed incompatible ABI changes.
+///
+/// @param d the @ref corpus_diff to consider
+///
+/// @return true iff @p d carries subtype changes that are deemed
+/// incompatible ABI changes.
+bool
+leaf_reporter::diff_has_net_changes(const corpus_diff *d) const
+{
+  if (!d)
+    return false;
+
+  const corpus_diff::diff_stats& stats = const_cast<corpus_diff*>(d)->
+    apply_filters_and_suppressions_before_reporting();
+
+  // Logic here should match emit_diff_stats.
+  return (d->architecture_changed()
+         || d->soname_changed()
+         || stats.net_num_func_removed()
+         || stats.net_num_leaf_type_changes()
+         || stats.net_num_leaf_func_changes()
+         || stats.net_num_func_added()
+         || stats.net_num_vars_removed()
+         || stats.net_num_leaf_var_changes()
+         || stats.net_num_vars_added()
+         || stats.net_num_removed_unreachable_types()
+         || stats.net_num_changed_unreachable_types()
+         || stats.net_num_added_unreachable_types()
+         || stats.net_num_removed_func_syms()
+         || stats.net_num_added_func_syms()
+         || stats.net_num_removed_var_syms()
+         || stats.net_num_added_var_syms());
+}
+
 /// Report the changes carried by the diffs contained in an instance
 /// of @ref string_diff_ptr_map.
 ///
index 5da9ef9730e72622f96d569286cf0a2348f31367..ea94f0bdd8e89740ae8cbc24a83b810ef9e3e934 100644 (file)
@@ -165,6 +165,15 @@ test-abidiff-exit/test-decl-enum-v1.o \
 test-abidiff-exit/test-decl-enum-report.txt \
 test-abidiff-exit/test-decl-enum-report-2.txt \
 test-abidiff-exit/test-decl-enum-report-3.txt \
+test-abidiff-exit/test-net-change.abignore \
+test-abidiff-exit/test-net-change-v0.c \
+test-abidiff-exit/test-net-change-v0.o \
+test-abidiff-exit/test-net-change-v1.c \
+test-abidiff-exit/test-net-change-v1.o \
+test-abidiff-exit/test-net-change-report0.txt \
+test-abidiff-exit/test-net-change-report1.txt \
+test-abidiff-exit/test-net-change-report2.txt \
+test-abidiff-exit/test-net-change-report3.txt \
 \
 test-diff-dwarf/test0-v0.cc            \
 test-diff-dwarf/test0-v0.o                     \
diff --git a/tests/data/test-abidiff-exit/test-net-change-report0.txt b/tests/data/test-abidiff-exit/test-net-change-report0.txt
new file mode 100644 (file)
index 0000000..66712b0
--- /dev/null
@@ -0,0 +1,43 @@
+Functions changes summary: 1 Removed, 2 Changed, 1 Added functions
+Variables changes summary: 1 Removed, 1 Changed, 1 Added variables
+
+1 Removed function:
+
+  [D] 'function int fun_removed()'    {fun_removed}
+
+1 Added function:
+
+  [A] 'function long int fun_added()'    {fun_added}
+
+2 functions with some indirect sub-type change:
+
+  [C] 'function int fun_changed()' has some indirect sub-type changes:
+    return type changed:
+      type name changed from 'int' to 'long int'
+      type size changed from 32 to 64 (in bits)
+
+  [C] 'function void victim(type_changed*)' has some indirect sub-type changes:
+    parameter 1 of type 'type_changed*' has sub-type changes:
+      in pointed to type 'struct type_changed':
+        type size changed from 32 to 64 (in bits)
+        1 data member change:
+          type of 'int type_changed::x' changed:
+            type name changed from 'int' to 'long int'
+            type size changed from 32 to 64 (in bits)
+
+1 Removed variable:
+
+  [D] 'int var_removed'    {var_removed}
+
+1 Added variable:
+
+  [A] 'long int var_added'    {var_added}
+
+1 Changed variable:
+
+  [C] 'int var_changed' was changed to 'long int var_changed':
+    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-net-change-report1.txt b/tests/data/test-abidiff-exit/test-net-change-report1.txt
new file mode 100644 (file)
index 0000000..4dd6096
--- /dev/null
@@ -0,0 +1,3 @@
+Functions changes summary: 0 Removed (1 filtered out), 0 Changed (2 filtered out), 0 Added (1 filtered out) functions
+Variables changes summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added (1 filtered out) variables
+
diff --git a/tests/data/test-abidiff-exit/test-net-change-report2.txt b/tests/data/test-abidiff-exit/test-net-change-report2.txt
new file mode 100644 (file)
index 0000000..ca3b3e0
--- /dev/null
@@ -0,0 +1,42 @@
+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 fun_removed()'    {fun_removed}
+
+1 Added function:
+
+  [A] 'function long int fun_added()'    {fun_added}
+
+1 function with some sub-type change:
+
+  [C] 'function int fun_changed()' 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 var_removed'    {var_removed}
+
+1 Added variable:
+
+  [A] 'long int var_added'    {var_added}
+
+1 Changed variable:
+
+  [C] 'int var_changed' was changed to 'long int var_changed':
+    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 type_changed' changed:
+  type size changed from 32 to 64 (in bits)
+  there are data member changes:
+    type 'int' of 'type_changed::x' 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-net-change-report3.txt b/tests/data/test-abidiff-exit/test-net-change-report3.txt
new file mode 100644 (file)
index 0000000..4856a77
--- /dev/null
@@ -0,0 +1,5 @@
+Leaf changes summary: 0 artifact changed (3 filtered out)
+Changed leaf types summary: 0 (1 filtered out) leaf type changed
+Removed/Changed/Added functions summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added function (1 filtered out)
+Removed/Changed/Added variables summary: 0 Removed (1 filtered out), 0 Changed (1 filtered out), 0 Added variable (1 filtered out)
+
diff --git a/tests/data/test-abidiff-exit/test-net-change-v0.c b/tests/data/test-abidiff-exit/test-net-change-v0.c
new file mode 100644 (file)
index 0000000..684b9c6
--- /dev/null
@@ -0,0 +1,14 @@
+int var_removed = 0;
+int fun_removed() { return 0; }
+
+int var_changed = 0;
+int fun_changed() { return 0; }
+
+struct type_removed {
+  int x;
+};
+struct type_changed {
+  int x;
+};
+
+void victim(struct type_changed * dummy) { (void)dummy->x; }
diff --git a/tests/data/test-abidiff-exit/test-net-change-v0.o b/tests/data/test-abidiff-exit/test-net-change-v0.o
new file mode 100644 (file)
index 0000000..bd2c744
Binary files /dev/null and b/tests/data/test-abidiff-exit/test-net-change-v0.o differ
diff --git a/tests/data/test-abidiff-exit/test-net-change-v1.c b/tests/data/test-abidiff-exit/test-net-change-v1.c
new file mode 100644 (file)
index 0000000..7b2a4ad
--- /dev/null
@@ -0,0 +1,14 @@
+long var_added = 0;
+long fun_added() { return 0; }
+
+long var_changed = 0;
+long fun_changed() { return 0; }
+
+struct type_added {
+  long x;
+};
+struct type_changed {
+  long x;
+};
+
+void victim(struct type_changed * dummy) { (void)dummy->x; }
diff --git a/tests/data/test-abidiff-exit/test-net-change-v1.o b/tests/data/test-abidiff-exit/test-net-change-v1.o
new file mode 100644 (file)
index 0000000..994ca58
Binary files /dev/null and b/tests/data/test-abidiff-exit/test-net-change-v1.o differ
diff --git a/tests/data/test-abidiff-exit/test-net-change.abignore b/tests/data/test-abidiff-exit/test-net-change.abignore
new file mode 100644 (file)
index 0000000..6ba2118
--- /dev/null
@@ -0,0 +1,8 @@
+[suppress_function]
+  name_regexp = ^fun_
+
+[suppress_variable]
+  name_regexp = ^var_
+
+[suppress_type]
+  name_regexp = ^type_
index 244de2aaff1fee9bdd5f92b2523d38ff73ccb571..936d1d630a8dbc1f59037af00d0dec2fe85ca429 100644 (file)
@@ -239,6 +239,44 @@ InOutSpec in_out_specs[] =
     "data/test-abidiff-exit/test-decl-enum-report-3.txt",
     "output/test-abidiff-exit/test-decl-enum-report-3.txt"
   },
+  {
+    "data/test-abidiff-exit/test-net-change-v0.o",
+    "data/test-abidiff-exit/test-net-change-v1.o",
+    "",
+    "--no-default-suppression --no-show-locs",
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
+    "data/test-abidiff-exit/test-net-change-report0.txt",
+    "output/test-abidiff-exit/test-net-change-report0.txt"
+  },
+  {
+    "data/test-abidiff-exit/test-net-change-v0.o",
+    "data/test-abidiff-exit/test-net-change-v1.o",
+    "data/test-abidiff-exit/test-net-change.abignore",
+    "--no-default-suppression --no-show-locs",
+    abigail::tools_utils::ABIDIFF_OK,
+    "data/test-abidiff-exit/test-net-change-report1.txt",
+    "output/test-abidiff-exit/test-net-change-report1.txt"
+  },
+  {
+    "data/test-abidiff-exit/test-net-change-v0.o",
+    "data/test-abidiff-exit/test-net-change-v1.o",
+    "",
+    "--no-default-suppression --no-show-locs --leaf-changes-only",
+    abigail::tools_utils::ABIDIFF_ABI_CHANGE
+    | abigail::tools_utils::ABIDIFF_ABI_INCOMPATIBLE_CHANGE,
+    "data/test-abidiff-exit/test-net-change-report2.txt",
+    "output/test-abidiff-exit/test-net-change-report2.txt"
+  },
+  {
+    "data/test-abidiff-exit/test-net-change-v0.o",
+    "data/test-abidiff-exit/test-net-change-v1.o",
+    "data/test-abidiff-exit/test-net-change.abignore",
+    "--no-default-suppression --no-show-locs --leaf-changes-only",
+    abigail::tools_utils::ABIDIFF_OK,
+    "data/test-abidiff-exit/test-net-change-report3.txt",
+    "output/test-abidiff-exit/test-net-change-report3.txt"
+  },
   {0, 0, 0 ,0,  abigail::tools_utils::ABIDIFF_OK, 0, 0}
 };
 
This page took 0.060808 seconds and 5 git commands to generate.