diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/recipes/01-test_symbol_presence.t | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/test/recipes/01-test_symbol_presence.t b/test/recipes/01-test_symbol_presence.t new file mode 100644 index 0000000000..619519c5b5 --- /dev/null +++ b/test/recipes/01-test_symbol_presence.t @@ -0,0 +1,115 @@ +#! /usr/bin/env perl +# -*- mode: Perl -*- +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use File::Spec::Functions qw(devnull); +use OpenSSL::Test qw(:DEFAULT srctop_file bldtop_dir bldtop_file); +use OpenSSL::Test::Utils; + +setup("test_symbol_presence"); + +plan skip_all => "Only useful when building shared libraries" + if disabled("shared"); + +my @libnames = ("crypto", "ssl"); +my $testcount = scalar @libnames; + +plan tests => $testcount * 2; + +note + "NOTE: developper test! It's possible that it won't run on your\n", + "platform, and that's perfectly fine. This is mainly for developers\n", + "on Unix to check that our shared libraries are consistent with the\n", + "ordinals (util/*.num in the source tree), something that should be\n", + "good enough a check for the other platforms as well.\n"; + +foreach my $libname (@libnames) { + SKIP: + { + my $shlibpath = bldtop_file("lib" . $libname . ".so"); + *OSTDERR = *STDERR; + *OSTDOUT = *STDOUT; + open STDERR, ">", devnull(); + open STDOUT, ">", devnull(); + my @nm_lines = map { s|\R$||; $_ } `nm -Pg $shlibpath 2> /dev/null`; + close STDERR; + close STDOUT; + *STDERR = *OSTDERR; + *STDOUT = *OSTDOUT; + skip "Can't run 'nm -Pg $shlibpath' => $?... ignoring", 2 + unless $? == 0; + + my $bldtop = bldtop_dir(); + my @def_lines; + indir $bldtop => sub { + my $mkdefpath = srctop_file("util", "mkdef.pl"); + @def_lines = map { s|\R$||; $_ } `$^X $mkdefpath $libname linux 2> /dev/null`; + ok($? == 0, "running 'cd $bldtop; $^X $mkdefpath $libname linux' => $?"); + }, create => 0, cleanup => 0; + + note "Number of lines in \@nm_lines before massaging: ", scalar @nm_lines; + note "Number of lines in \@def_lines before massaging: ", scalar @def_lines; + + # Massage the nm output to only contain defined symbols + @nm_lines = sort map { s| .*||; $_ } grep(m|.* [BCDT] .*|, @nm_lines); + + # Massage the mkdef.pl output to only contain global symbols + # The output we got is in Unix .map format, which has a global + # and a local section. We're only interested in the global + # section. + my $in_global = 0; + @def_lines = + sort + map { s|;||; s|\s+||g; $_ } + grep { $in_global = 1 if m|global:|; + $in_global = 0 if m|local:|; + $in_global && m|;|; } @def_lines; + + note "Number of lines in \@nm_lines after massaging: ", scalar @nm_lines; + note "Number of lines in \@def_lines after massaging: ", scalar @def_lines; + + # Maintain lists of symbols that are missing in the shared library, + # or that are extra. + my @missing = (); + my @extra = (); + + while (scalar @nm_lines || scalar @def_lines) { + my $nm_first = $nm_lines[0]; + my $def_first = $def_lines[0]; + + if (!defined($nm_first)) { + push @missing, shift @def_lines; + } elsif (!defined($def_first)) { + push @extra, shift @nm_lines; + } elsif ($nm_first gt $def_first) { + push @missing, shift @def_lines; + } elsif ($nm_first lt $def_first) { + push @extra, shift @nm_lines; + } else { + shift @def_lines; + shift @nm_lines; + } + } + + if (scalar @missing) { + note "The following symbols are missing in lib$libname.so:"; + foreach (@missing) { + note " $_"; + } + } + if (scalar @extra) { + note "The following symbols are extra in lib$libname.so:"; + foreach (@extra) { + note " $_"; + } + } + ok(scalar @missing == 0, + "check that there are no missing symbols in lib$libname.so"); + } +} |