summaryrefslogtreecommitdiff
path: root/scripts/t
diff options
context:
space:
mode:
authorRaphaël Hertzog <hertzog@debian.org>2010-01-11 14:46:03 +0100
committerRaphaël Hertzog <hertzog@debian.org>2010-01-11 19:24:21 +0100
commitda19cee896d19264a1c733a93646a37ffb4d1fd0 (patch)
treedc511931e667985a159872a906958096aa444de5 /scripts/t
parentfa6739b81239f053243014dbbba18c2328cd388c (diff)
downloaddpkg-da19cee896d19264a1c733a93646a37ffb4d1fd0.tar.gz
scripts/t/200_Dpkg_Shlibs.t: extend test suite to cover symbol patterns functionality
Signed-off-by: Modestas Vainius <modax@debian.org> Signed-off-by: Raphaël Hertzog <hertzog@debian.org>
Diffstat (limited to 'scripts/t')
-rw-r--r--scripts/t/200_Dpkg_Shlibs.t146
-rw-r--r--scripts/t/200_Dpkg_Shlibs/patterns.cpp98
-rw-r--r--scripts/t/200_Dpkg_Shlibs/patterns.map4
-rw-r--r--scripts/t/200_Dpkg_Shlibs/patterns.symbols45
4 files changed, 291 insertions, 2 deletions
diff --git a/scripts/t/200_Dpkg_Shlibs.t b/scripts/t/200_Dpkg_Shlibs.t
index bd2e9a352..327d6854e 100644
--- a/scripts/t/200_Dpkg_Shlibs.t
+++ b/scripts/t/200_Dpkg_Shlibs.t
@@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-use Test::More tests => 65;
+use Test::More tests => 97;
use Cwd;
use IO::String;
@@ -135,7 +135,7 @@ ok( $sym_file->get_new_symbols($sym_file_old), 'has new symbols' );
ok( $sym_file_old->get_lost_symbols($sym_file), 'has lost symbols' );
is( $sym_file_old->lookup_symbol('__bss_start@Base', ['libc.so.6']),
- undef, 'internal symbols are blacklisted');
+ undef, 'internal symbols are blacklisted' );
$sym = $sym_file->lookup_symbol('_errno@GLIBC_2.0', ['libc.so.6'], 1);
isa_ok($sym, 'Dpkg::Shlibs::Symbol');
@@ -409,3 +409,145 @@ $tmp[1]->{teststruct}{foo} = 3;
$tmp[1]->{testfield} = 3;
is ( $sym->{teststruct}{foo}, 2, 'struct changed via sclone()' );
is ( $sym->{testfield}, 1, 'original field not changed' );
+
+############ Test symbol patterns ###########
+sub load_patterns_obj {
+ $obj = Dpkg::Shlibs::Objdump::Object->new();
+ open $objdump, '<', "$tmpdir/objdump.patterns"
+ or die "$tmpdir/objdump.patterns: $!";
+ $obj->_parse($objdump);
+ close $objdump;
+ return $obj;
+}
+
+sub load_patterns_symbols {
+ $sym_file = Dpkg::Shlibs::SymbolFile->new(file => "$datadir/patterns.symbols");
+ return $sym_file;
+}
+
+load_patterns_obj();
+$sym_file_dup = load_patterns_symbols();
+load_patterns_symbols();
+
+save_load_test($sym_file, 'save -> load test of patterns template', template_mode => 1);
+
+isnt( $sym_file->get_soname_patterns('libpatterns.so.1') , 0,
+ "patterns.symbols has patterns" );
+
+$sym_file->merge_symbols($obj, '100.MISSING');
+
+@tmp = map { $_->get_symbolname() } $sym_file->get_lost_symbols($sym_file_dup);
+is_deeply( \@tmp, [], "no LOST symbols if all patterns matched." );
+@tmp = map { $_->get_symbolname() } $sym_file->get_new_symbols($sym_file_dup);
+is_deeply( \@tmp, [], "no NEW symbols if all patterns matched." );
+
+# Pattern resolution order: aliases (c++, wildcard), generic
+$sym = $sym_file->lookup_symbol('VERSION_1@VERSION_1',['libpatterns.so.1']);
+is ( $sym->{minver}, '1', "specific VERSION_1 symbol" );
+
+$sym = $sym_file->lookup_symbol('_ZN3NSB8Wildcard16wildcard_method1Ev@VERSION_1', ['libpatterns.so.1']);
+is ( $sym->{minver}, '1.method1', "specific symbol prefered over pattern" );
+
+$sym = $sym_file->lookup_symbol('_ZN3NSB8Wildcard16wildcard_method2Ev@VERSION_1', ['libpatterns.so.1']);
+is ( $sym->{minver}, '1.method2', "c++ alias pattern preferred over generic pattern" );
+is ( $sym->get_pattern()->get_symbolname(), 'NSB::Wildcard::wildcard_method2()@VERSION_1' );
+
+$sym = $sym_file->lookup_symbol('_ZN3NSB8WildcardD1Ev@VERSION_1', ['libpatterns.so.1']);
+is ( $sym->{minver}, '1.generic', 'generic (wildcard & c++) pattern covers the rest (destructor)' );
+is ( $sym->get_pattern()->get_symbolname(), '*@VERSION_1' );
+
+# Lookup private pattern
+my @private_symnames = sort qw(
+ _ZN3NSA6ClassA7Private11privmethod1Ei@Base
+ _ZN3NSA6ClassA7Private11privmethod2Ei@Base
+ _ZN3NSA6ClassA7PrivateC1Ev@Base
+ _ZN3NSA6ClassA7PrivateC2Ev@Base
+ _ZN3NSA6ClassA7PrivateD0Ev@Base
+ _ZN3NSA6ClassA7PrivateD1Ev@Base
+ _ZN3NSA6ClassA7PrivateD2Ev@Base
+ _ZTIN3NSA6ClassA7PrivateE@Base
+ _ZTSN3NSA6ClassA7PrivateE@Base
+ _ZTVN3NSA6ClassA7PrivateE@Base
+);
+$sym = $sym_file->create_symbol('(c++|regex|optional)NSA::ClassA::Private(::.*)?@Base 1');
+$pat = $sym_file->lookup_pattern($sym, ['libpatterns.so.1']);
+isnt( $pat, undef, 'pattern for private class has been found' );
+is_deeply( [ sort map { $_->get_symbolname() } $pat->get_pattern_matches() ],
+ \@private_symnames, "private pattern matched expected symbols" );
+ok( ($pat->get_pattern_matches())[0]->is_optional(),
+ "private symbol is optional like its pattern" );
+ok( $sym_file->lookup_symbol(($pat->get_pattern_matches())[0]->get_symbolname(), ['libpatterns.so.1']),
+ "lookup_symbol() finds symbols matched by pattern (after merge)"),
+
+# Get rid of a private symbol, it should not be lost
+delete $obj->{dynsyms}{$private_symnames[0]};
+load_patterns_symbols();
+$sym_file->merge_symbols($obj, '100.MISSING');
+
+$pat = $sym_file->lookup_pattern($sym, ['libpatterns.so.1']);
+@tmp = map { $_->get_symbolname() } $sym_file->get_lost_symbols($sym_file_dup);
+is_deeply( \@tmp, [], "no LOST symbols when got rid of patterned optional symbol." );
+ok( ! $pat->{deprecated} , "there are still matches, pattern is not deprecated." );
+
+# Get rid of all private symbols, the pattern should be deprecated.
+foreach my $tmp (@private_symnames) {
+ delete $obj->{dynsyms}{$tmp};
+}
+load_patterns_symbols();
+$sym_file->merge_symbols($obj, '100.MISSING');
+
+$pat = $sym_file->lookup_pattern($sym, ['libpatterns.so.1'], 1);
+@tmp = $sym_file->get_lost_symbols($sym_file_dup);
+is_deeply( \@tmp, [ ],
+ "All private symbols gone, but pattern is not LOST because it is optional." );
+is( $pat->{deprecated}, '100.MISSING',
+ "All private symbols gone - pattern deprecated." );
+
+# Internal symbols. All covered by the pattern?
+@tmp = grep { $_->get_symbolname() =~ /Internal/ } values %{$sym_file->{objects}{'libpatterns.so.1'}{syms}};
+$sym = $sym_file->create_symbol('(regex|c++)^_Z(T[ISV])?N3NSA6ClassA8Internal.*@Base$ 1.internal'),
+$pat = $sym_file->lookup_pattern($sym, ['libpatterns.so.1']);
+is_deeply ([ sort $pat->get_pattern_matches() ], [ sort @tmp ],
+ "Pattern covers all internal symbols");
+is ( $tmp[0]->{minver}, '1.internal' );
+
+# Delete matches of the non-optional pattern
+$sym = $sym_file->create_symbol('(c++)"non-virtual thunk to NSB::ClassD::generate_vt(char const*) const@Base" 1');
+$pat = $sym_file->lookup_pattern($sym, ['libpatterns.so.1']);
+isnt( $pat, undef, 'lookup_pattern() finds alias-based pattern' );
+
+is( scalar($pat->get_pattern_matches()), 2, "two matches for the generate_vt pattern" );
+foreach my $tmp ($pat->get_pattern_matches()) {
+ delete $obj->{dynsyms}{$tmp->get_symbolname()};
+}
+load_patterns_symbols();
+$sym_file->merge_symbols($obj, '100.MISSING');
+
+$pat = $sym_file->lookup_pattern($sym, ['libpatterns.so.1'], 1);
+@tmp = map { $sym_file->lookup_pattern($_, ['libpatterns.so.1'], 1) }
+ $sym_file->get_lost_symbols($sym_file_dup);
+is_deeply( \@tmp, [ $pat ], "No matches - generate_vt() pattern is LOST." );
+is( $pat->{deprecated}, '100.MISSING',
+ "No matches - generate_vt() pattern is deprecated." );
+
+# Pattern undeprecation when matches are discovered
+load_patterns_obj();
+load_patterns_symbols();
+
+$pat = $sym_file_dup->lookup_pattern($sym, ['libpatterns.so.1']);
+$pat->{deprecated} = '0.1-1';
+$pat = $sym_file->lookup_pattern($sym, ['libpatterns.so.1']);
+$pat->{deprecated} = '0.1-1';
+
+$sym_file->merge_symbols($obj, '100.FOUND');
+ok( ! $pat->{deprecated},
+ "Previously deprecated pattern with matches got undeprecated" );
+is( $pat->{minver}, '100.FOUND',
+ "Previously deprecated pattern with matches got minver bumped" );
+@tmp = map { $_->get_symbolspec(1) } $sym_file->get_new_symbols($sym_file_dup);
+is_deeply( \@tmp, [ $pat->get_symbolspec(1) ],
+ "Previously deprecated pattern with matches is NEW. Matches themselves are not NEW." );
+foreach my $sym ($pat->get_pattern_matches()) {
+ ok( ! $sym->{deprecated}, $sym->get_symbolname().": not deprecated" );
+ is( $sym->{minver}, '100.FOUND', $sym->get_symbolname().": version bumped" );
+}
diff --git a/scripts/t/200_Dpkg_Shlibs/patterns.cpp b/scripts/t/200_Dpkg_Shlibs/patterns.cpp
new file mode 100644
index 000000000..ae4e74c17
--- /dev/null
+++ b/scripts/t/200_Dpkg_Shlibs/patterns.cpp
@@ -0,0 +1,98 @@
+#define EXPORT(x) x {}
+
+namespace NSA
+{
+ class ClassA
+ {
+ private:
+ class Private
+ {
+ public:
+ Private();
+ virtual ~Private();
+ void privmethod1(int);
+ void privmethod2(int);
+ };
+ Private* p;
+ class Internal
+ {
+ public:
+ Internal();
+ virtual ~Internal();
+ void internal_method1(char);
+ void internal_method2(char);
+ };
+ Internal* i;
+ public:
+ ClassA();
+ virtual ~ClassA();
+ virtual void generate_vt(const char*) const;
+ };
+
+ EXPORT(ClassA::Private::Private());
+ EXPORT(ClassA::Private::~Private());
+ EXPORT(void ClassA::Private::privmethod1(int));
+ EXPORT(void ClassA::Private::privmethod2(int));
+
+ EXPORT(ClassA::Internal::Internal());
+ EXPORT(ClassA::Internal::~Internal());
+ EXPORT(void ClassA::Internal::internal_method1(char));
+ EXPORT(void ClassA::Internal::internal_method2(char));
+
+ EXPORT(ClassA::ClassA());
+ EXPORT(ClassA::~ClassA());
+ EXPORT(void ClassA::generate_vt(const char*) const);
+};
+
+class ClassB
+{
+ public:
+ ClassB();
+ virtual ~ClassB();
+ virtual void generate_vt(const char*) const;
+};
+
+EXPORT(ClassB::ClassB());
+EXPORT(ClassB::~ClassB());
+EXPORT(void ClassB::generate_vt(const char*) const);
+
+class ClassC
+{
+ public:
+ ClassC();
+ virtual ~ClassC();
+ virtual void generate_vt(const char*) const;
+};
+
+EXPORT(ClassC::ClassC());
+EXPORT(ClassC::~ClassC());
+EXPORT(void ClassC::generate_vt(const char*) const);
+
+namespace NSB
+{
+ class ClassD : public NSA::ClassA, public ClassB, public ClassC
+ {
+ public:
+ ClassD();
+ virtual ~ClassD();
+ virtual void generate_vt(const char*) const;
+ };
+
+ EXPORT(ClassD::ClassD());
+ EXPORT(ClassD::~ClassD());
+ EXPORT(void ClassD::generate_vt(const char*) const);
+
+ class Wildcard {
+ public:
+ Wildcard();
+ ~Wildcard();
+
+ void wildcard_method1();
+ void wildcard_method2();
+ };
+
+ EXPORT(Wildcard::Wildcard());
+ EXPORT(Wildcard::~Wildcard());
+ EXPORT(void Wildcard::wildcard_method1());
+ EXPORT(void Wildcard::wildcard_method2());
+};
diff --git a/scripts/t/200_Dpkg_Shlibs/patterns.map b/scripts/t/200_Dpkg_Shlibs/patterns.map
new file mode 100644
index 000000000..15ed95008
--- /dev/null
+++ b/scripts/t/200_Dpkg_Shlibs/patterns.map
@@ -0,0 +1,4 @@
+VERSION_1 {
+ global:
+ _ZN3NSB8Wildcard*;
+};
diff --git a/scripts/t/200_Dpkg_Shlibs/patterns.symbols b/scripts/t/200_Dpkg_Shlibs/patterns.symbols
new file mode 100644
index 000000000..d8ebe8989
--- /dev/null
+++ b/scripts/t/200_Dpkg_Shlibs/patterns.symbols
@@ -0,0 +1,45 @@
+libpatterns.so.1 libpatterns1 #MINVER#
+ (c++)*@VERSION_1 1.generic
+ (c++|regex|optional)NSA::ClassA::Private(::.*)?@Base 1.private
+ (c++)NSB::Wildcard::wildcard_method2()@VERSION_1 1.method2
+ VERSION_1@VERSION_1 1
+ (regex|c++)^_Z(T[ISV])?N3NSA6ClassA8Internal.*@Base$ 1.internal
+ _ZN3NSA6ClassAC1Ev@Base 1
+ _ZN3NSA6ClassAC2Ev@Base 1
+ _ZN3NSA6ClassAD0Ev@Base 1
+ _ZN3NSA6ClassAD1Ev@Base 1
+ _ZN3NSA6ClassAD2Ev@Base 1
+ _ZN3NSB6ClassDC1Ev@Base 1
+ _ZN3NSB6ClassDC2Ev@Base 1
+ _ZN3NSB6ClassDD0Ev@Base 1
+ _ZN3NSB6ClassDD1Ev@Base 1
+ _ZN3NSB6ClassDD2Ev@Base 1
+ _ZN3NSB8Wildcard16wildcard_method1Ev@VERSION_1 1.method1
+ _ZN6ClassBC1Ev@Base 1
+ _ZN6ClassBC2Ev@Base 1
+ _ZN6ClassBD0Ev@Base 1
+ _ZN6ClassBD1Ev@Base 1
+ _ZN6ClassBD2Ev@Base 1
+ _ZN6ClassCC1Ev@Base 1
+ _ZN6ClassCC2Ev@Base 1
+ _ZN6ClassCD0Ev@Base 1
+ _ZN6ClassCD1Ev@Base 1
+ _ZN6ClassCD2Ev@Base 1
+ _ZNK3NSA6ClassA11generate_vtEPKc@Base 1
+ _ZNK3NSB6ClassD11generate_vtEPKc@Base 1
+ _ZNK6ClassB11generate_vtEPKc@Base 1
+ _ZNK6ClassC11generate_vtEPKc@Base 1
+ _ZTI6ClassB@Base 1
+ _ZTI6ClassC@Base 1
+ _ZTIN3NSA6ClassAE@Base 1
+ _ZTIN3NSB6ClassDE@Base 1
+ _ZTS6ClassB@Base 1
+ _ZTS6ClassC@Base 1
+ _ZTSN3NSA6ClassAE@Base 1
+ _ZTSN3NSB6ClassDE@Base 1
+ _ZTV6ClassB@Base 1
+ _ZTV6ClassC@Base 1
+ _ZTVN3NSA6ClassAE@Base 1
+ _ZTVN3NSB6ClassDE@Base 1
+ (c++)"non-virtual thunk to NSB::ClassD::generate_vt(char const*) const@Base" 1
+ (c++)"non-virtual thunk to NSB::ClassD::~ClassD()@Base" 1