Bug 19082 - Recognize suppression spec files
authorOndrej Oprala <ooprala@redhat.com>
Tue, 13 Oct 2015 07:19:47 +0000 (09:19 +0200)
committerOndrej Oprala <ooprala@redhat.com>
Tue, 13 Oct 2015 07:19:47 +0000 (09:19 +0200)
When abipkgdiff is invoked on a set of packages, the newer (second) one is also
inspected for files matching the pattern '*.abignore', whose contents are read
and interpreted as suppression specifications.

* tests/data/Makefile.am: Add new test material to the build system.
* tests/data/test-diff-pkg/dirpkg-{0-dir1,{1,2}-dir2}/dir.abignore:
A test suppression specification.
* tests/data/test-diff-pkg/dirpkg-{2,3}-dir2/.abignore: Likewise.
* tests/data/test-diff-pkg/dirpkg-3.suppr: Likewise.
* tests/data/test-diff-pkg/dirpkg-{1,2,3}-dir{1,2}/libobj-v0.so: New
binary test inputs.
* tests/data/test-diff-pkg/dirpkg-{1,2,3}-dir{1,2}/obj-v0.cc: New test
source files
* tests/data/test-diff-pkg/dirpkg-{1,2,3}-report-{0,1}.txt: New
reference outputs
* tests/test-diff-pkg.cc: Adjust to run the new tests.
* tools/abipkgdiff.cc (prog_options): New static pointer to struct
opts.
(file_tree_walker_callback_fn): Rename to
first_package_tree_walker_callback_fn.
(second_package_tree_walker_callback_fn): Check for ELF files just
like the previous function but additionally check for files
ending with ".abignore", unless disabled from the command line.
({create_maps_of_package,extract_package_and_map_its}_content):
Add a callback as a new argument.
(main) handle the new "--no-abignore" option, which turns off
the search for suppression files within the new package.

Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
27 files changed:
tests/data/Makefile.am
tests/data/test-diff-pkg/dirpkg-0-dir1/dir.abignore [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-1-dir1/libobj-v0.so [new file with mode: 0755]
tests/data/test-diff-pkg/dirpkg-1-dir1/obj-v0.cc [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-1-dir2/dir.abignore [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-1-dir2/libobj-v0.so [new file with mode: 0755]
tests/data/test-diff-pkg/dirpkg-1-dir2/obj-v0.cc [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-1-report-0.txt [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-1-report-1.txt [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-2-dir1/libobj-v0.so [new file with mode: 0755]
tests/data/test-diff-pkg/dirpkg-2-dir1/obj-v0.cc [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-2-dir2/.abignore [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-2-dir2/dir.abignore [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-2-dir2/libobj-v0.so [new file with mode: 0755]
tests/data/test-diff-pkg/dirpkg-2-dir2/obj-v0.cc [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-2-report-0.txt [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-2-report-1.txt [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-3-dir1/libobj-v0.so [new file with mode: 0755]
tests/data/test-diff-pkg/dirpkg-3-dir1/obj-v0.cc [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-3-dir2/.abignore [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-3-dir2/libobj-v0.so [new file with mode: 0755]
tests/data/test-diff-pkg/dirpkg-3-dir2/obj-v0.cc [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-3-report-0.txt [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-3-report-1.txt [new file with mode: 0644]
tests/data/test-diff-pkg/dirpkg-3.suppr [new file with mode: 0644]
tests/test-diff-pkg.cc
tools/abipkgdiff.cc

index 73d02e1..967e225 100644 (file)
@@ -892,11 +892,35 @@ test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64--libsigc++-2.0-0v5_2.4.1-1ubuntu2
 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 \
diff --git a/tests/data/test-diff-pkg/dirpkg-0-dir1/dir.abignore b/tests/data/test-diff-pkg/dirpkg-0-dir1/dir.abignore
new file mode 100644 (file)
index 0000000..d03917d
--- /dev/null
@@ -0,0 +1,4 @@
+#taken from test5-fn-supprt-0.suppr
+[suppress_function]
+  # suppress change reports for a function which name is 'bar' ...
+  name = bar
diff --git a/tests/data/test-diff-pkg/dirpkg-1-dir1/libobj-v0.so b/tests/data/test-diff-pkg/dirpkg-1-dir1/libobj-v0.so
new file mode 100755 (executable)
index 0000000..7373521
Binary files /dev/null and b/tests/data/test-diff-pkg/dirpkg-1-dir1/libobj-v0.so differ
diff --git a/tests/data/test-diff-pkg/dirpkg-1-dir1/obj-v0.cc b/tests/data/test-diff-pkg/dirpkg-1-dir1/obj-v0.cc
new file mode 100644 (file)
index 0000000..5a016dd
--- /dev/null
@@ -0,0 +1,15 @@
+// Compile with:
+// g++ -g -shared -o libobj-v0.so obj-v0.cc
+
+struct S
+{
+  int mem0;
+
+  S()
+    : mem0()
+  {}
+};
+
+void
+bar(S&)
+{}
diff --git a/tests/data/test-diff-pkg/dirpkg-1-dir2/dir.abignore b/tests/data/test-diff-pkg/dirpkg-1-dir2/dir.abignore
new file mode 100644 (file)
index 0000000..d03917d
--- /dev/null
@@ -0,0 +1,4 @@
+#taken from test5-fn-supprt-0.suppr
+[suppress_function]
+  # suppress change reports for a function which name is 'bar' ...
+  name = bar
diff --git a/tests/data/test-diff-pkg/dirpkg-1-dir2/libobj-v0.so b/tests/data/test-diff-pkg/dirpkg-1-dir2/libobj-v0.so
new file mode 100755 (executable)
index 0000000..0032f73
Binary files /dev/null and b/tests/data/test-diff-pkg/dirpkg-1-dir2/libobj-v0.so differ
diff --git a/tests/data/test-diff-pkg/dirpkg-1-dir2/obj-v0.cc b/tests/data/test-diff-pkg/dirpkg-1-dir2/obj-v0.cc
new file mode 100644 (file)
index 0000000..65f6bab
--- /dev/null
@@ -0,0 +1,17 @@
+// Compile with:
+// g++ -g -shared -o libobj-v0.so obj-v0.cc
+
+struct S
+{
+  int  mem0;
+  char mem1;
+
+  S()
+    : mem0(),
+      mem1()
+  {}
+};
+
+void
+bar(S&)
+{}
diff --git a/tests/data/test-diff-pkg/dirpkg-1-report-0.txt b/tests/data/test-diff-pkg/dirpkg-1-report-0.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/data/test-diff-pkg/dirpkg-1-report-1.txt b/tests/data/test-diff-pkg/dirpkg-1-report-1.txt
new file mode 100644 (file)
index 0000000..c7c9226
--- /dev/null
@@ -0,0 +1,16 @@
+================ 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'===============
+
diff --git a/tests/data/test-diff-pkg/dirpkg-2-dir1/libobj-v0.so b/tests/data/test-diff-pkg/dirpkg-2-dir1/libobj-v0.so
new file mode 100755 (executable)
index 0000000..327577d
Binary files /dev/null and b/tests/data/test-diff-pkg/dirpkg-2-dir1/libobj-v0.so differ
diff --git a/tests/data/test-diff-pkg/dirpkg-2-dir1/obj-v0.cc b/tests/data/test-diff-pkg/dirpkg-2-dir1/obj-v0.cc
new file mode 100644 (file)
index 0000000..206a265
--- /dev/null
@@ -0,0 +1,22 @@
+// 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&)
+{}
diff --git a/tests/data/test-diff-pkg/dirpkg-2-dir2/.abignore b/tests/data/test-diff-pkg/dirpkg-2-dir2/.abignore
new file mode 100644 (file)
index 0000000..b8f8197
--- /dev/null
@@ -0,0 +1,2 @@
+[suppress_function]
+  name = foo
diff --git a/tests/data/test-diff-pkg/dirpkg-2-dir2/dir.abignore b/tests/data/test-diff-pkg/dirpkg-2-dir2/dir.abignore
new file mode 100644 (file)
index 0000000..c06dd56
--- /dev/null
@@ -0,0 +1,2 @@
+[suppress_function]
+  name = bar
diff --git a/tests/data/test-diff-pkg/dirpkg-2-dir2/libobj-v0.so b/tests/data/test-diff-pkg/dirpkg-2-dir2/libobj-v0.so
new file mode 100755 (executable)
index 0000000..de46f91
Binary files /dev/null and b/tests/data/test-diff-pkg/dirpkg-2-dir2/libobj-v0.so differ
diff --git a/tests/data/test-diff-pkg/dirpkg-2-dir2/obj-v0.cc b/tests/data/test-diff-pkg/dirpkg-2-dir2/obj-v0.cc
new file mode 100644 (file)
index 0000000..b96530e
--- /dev/null
@@ -0,0 +1,25 @@
+// 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&)
+{}
diff --git a/tests/data/test-diff-pkg/dirpkg-2-report-0.txt b/tests/data/test-diff-pkg/dirpkg-2-report-0.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/data/test-diff-pkg/dirpkg-2-report-1.txt b/tests/data/test-diff-pkg/dirpkg-2-report-1.txt
new file mode 100644 (file)
index 0000000..c7c9226
--- /dev/null
@@ -0,0 +1,16 @@
+================ 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'===============
+
diff --git a/tests/data/test-diff-pkg/dirpkg-3-dir1/libobj-v0.so b/tests/data/test-diff-pkg/dirpkg-3-dir1/libobj-v0.so
new file mode 100755 (executable)
index 0000000..327577d
Binary files /dev/null and b/tests/data/test-diff-pkg/dirpkg-3-dir1/libobj-v0.so differ
diff --git a/tests/data/test-diff-pkg/dirpkg-3-dir1/obj-v0.cc b/tests/data/test-diff-pkg/dirpkg-3-dir1/obj-v0.cc
new file mode 100644 (file)
index 0000000..206a265
--- /dev/null
@@ -0,0 +1,22 @@
+// 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&)
+{}
diff --git a/tests/data/test-diff-pkg/dirpkg-3-dir2/.abignore b/tests/data/test-diff-pkg/dirpkg-3-dir2/.abignore
new file mode 100644 (file)
index 0000000..b8f8197
--- /dev/null
@@ -0,0 +1,2 @@
+[suppress_function]
+  name = foo
diff --git a/tests/data/test-diff-pkg/dirpkg-3-dir2/libobj-v0.so b/tests/data/test-diff-pkg/dirpkg-3-dir2/libobj-v0.so
new file mode 100755 (executable)
index 0000000..de46f91
Binary files /dev/null and b/tests/data/test-diff-pkg/dirpkg-3-dir2/libobj-v0.so differ
diff --git a/tests/data/test-diff-pkg/dirpkg-3-dir2/obj-v0.cc b/tests/data/test-diff-pkg/dirpkg-3-dir2/obj-v0.cc
new file mode 100644 (file)
index 0000000..b96530e
--- /dev/null
@@ -0,0 +1,25 @@
+// 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&)
+{}
diff --git a/tests/data/test-diff-pkg/dirpkg-3-report-0.txt b/tests/data/test-diff-pkg/dirpkg-3-report-0.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/data/test-diff-pkg/dirpkg-3-report-1.txt b/tests/data/test-diff-pkg/dirpkg-3-report-1.txt
new file mode 100644 (file)
index 0000000..d0135b4
--- /dev/null
@@ -0,0 +1,16 @@
+================ 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'===============
+
diff --git a/tests/data/test-diff-pkg/dirpkg-3.suppr b/tests/data/test-diff-pkg/dirpkg-3.suppr
new file mode 100644 (file)
index 0000000..c06dd56
--- /dev/null
@@ -0,0 +1,2 @@
+[suppress_function]
+  name = bar
index 2e56d31..f788282 100644 (file)
 
 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;
@@ -54,15 +56,79 @@ struct InOutSpec
 
 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
   {
@@ -71,6 +137,7 @@ static InOutSpec in_out_specs[] =
     "",
     "",
     "",
+    "",
     "data/test-diff-pkg/tarpkg-0-report-0.txt",
     "output/test-diff-pkg/tarpkg-0-report-0.txt"
   },
@@ -80,6 +147,7 @@ static InOutSpec in_out_specs[] =
     "",
     "",
     "",
+    "",
     "data/test-diff-pkg/tarpkg-0-report-0.txt",
     "output/test-diff-pkg/tarpkg-0-report-0.txt"
   },
@@ -89,6 +157,7 @@ static InOutSpec in_out_specs[] =
     "",
     "",
     "",
+    "",
     "data/test-diff-pkg/tarpkg-0-report-0.txt",
     "output/test-diff-pkg/tarpkg-0-report-0.txt"
   },
@@ -98,6 +167,7 @@ static InOutSpec in_out_specs[] =
     "",
     "",
     "",
+    "",
     "data/test-diff-pkg/tarpkg-0-report-0.txt",
     "output/test-diff-pkg/tarpkg-0-report-0.txt"
   },
@@ -109,6 +179,7 @@ static InOutSpec in_out_specs[] =
     "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",
@@ -119,6 +190,7 @@ static InOutSpec in_out_specs[] =
   "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",
@@ -131,6 +203,7 @@ static InOutSpec in_out_specs[] =
   "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"
@@ -143,6 +216,7 @@ static InOutSpec in_out_specs[] =
   "",
   "",
   "",
+  "",
   "data/test-diff-pkg/test-rpm-report-3.txt",
   "output/test-diff-pkg/test-rpm-report-3.txt"
   },
@@ -152,6 +226,7 @@ static InOutSpec in_out_specs[] =
   "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",
@@ -163,6 +238,7 @@ static InOutSpec in_out_specs[] =
     "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",
@@ -176,6 +252,7 @@ static InOutSpec in_out_specs[] =
     "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",
@@ -183,13 +260,12 @@ static InOutSpec in_out_specs[] =
   },
 #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;
 
@@ -197,7 +273,8 @@ main()
   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 =
@@ -220,6 +297,14 @@ main()
           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;
@@ -242,6 +327,9 @@ main()
       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;
index 8dd8997..c8017fc 100644 (file)
@@ -60,6 +60,7 @@ using std::vector;
 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;
@@ -82,16 +83,21 @@ static bool verbose;
 /// 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;
@@ -108,6 +114,7 @@ struct options
   options()
     : display_usage(),
       missing_operand(),
+      abignore(true),
       keep_tmp_files(),
       compare_dso_only(),
       show_linkage_names(true),
@@ -146,6 +153,10 @@ public:
 /// 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
@@ -647,15 +658,15 @@ extract_package(const package& package)
 }
 
 /// 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);
@@ -668,6 +679,31 @@ file_tree_walker_callback_fn(const char *fpath,
   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.
@@ -860,7 +896,8 @@ compare(const elf_file& elf1,
 /// @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)
@@ -870,9 +907,7 @@ create_maps_of_package_content(package& package,
         << 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";
@@ -919,14 +954,15 @@ create_maps_of_package_content(package& package,
 /// @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;
 }
@@ -947,8 +983,10 @@ prepare_packages(package&  first_package,
                 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()
@@ -1142,6 +1180,8 @@ parse_command_line(int argc, char* argv[], options& opts)
        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"))
        {
@@ -1168,6 +1208,7 @@ int
 main(int argc, char* argv[])
 {
   options opts;
+  prog_options = &opts;
   vector<package_sptr> packages;
   if (!parse_command_line(argc, argv, opts))
     {