Commit 2b213daa authored by Simon McVittie's avatar Simon McVittie

Add (failing) test coverage for !23

This demonstrates the behaviour we want from !23.
Signed-off-by: Simon McVittie's avatarSimon McVittie <smcv@collabora.com>
parent c9f1dc7a
Pipeline #8086 passed with stage
in 8 minutes and 21 seconds
......@@ -152,10 +152,11 @@ include $(top_srcdir)/data/disabled.mk
# GNOME-style installed-tests
insttestsdir = $(libexecdir)/installed-tests/$(PACKAGE_TARNAME)
nobase_insttests_LTLIBRARIES =
if ENABLE_LIBRARY
# /!\ Order is important here: the helper library must come first
nobase_insttests_LTLIBRARIES = tests/red/libhelper.la \
nobase_insttests_LTLIBRARIES += tests/red/libhelper.la \
tests/green/libhelper.la \
tests/helper/libhelper.la \
tests/red/libnotgl.la \
......@@ -333,6 +334,57 @@ tests/shim/%.c: tests/shim/%.excluded tests/shim/%.shared tests/shim/%.symbols d
$@
endif
if ENABLE_SHARED
nobase_insttests_LTLIBRARIES += tests/version1/libunversionedabibreak.la \
tests/version2/libunversionedabibreak.la \
tests/version1/libunversionednumber.la \
tests/version2/libunversionednumber.la \
tests/version1/libunversionedsymbols.la \
tests/version2/libunversionedsymbols.la \
tests/version1/libversionedabibreak.la \
tests/version2/libversionedabibreak.la \
tests/version1/libversionedlikedbus.la \
tests/version2/libversionedlikedbus.la \
tests/version1/libversionedlikeglibc.la \
tests/version2/libversionedlikeglibc.la \
tests/version1/libversionednumber.la \
tests/version2/libversionednumber.la \
tests/version1/libversionedsymbols.la \
tests/version2/libversionedsymbols.la \
tests/version1/libversionedupgrade.la \
tests/version2/libversionedupgrade.la
tests_version1_libunversionedabibreak_la_LDFLAGS = -shared -version-number 1:0:0
tests_version2_libunversionedabibreak_la_LDFLAGS = -shared -version-number 1:0:0
tests_version1_libunversionednumber_la_LDFLAGS = -shared -version-number 1:0:0
tests_version2_libunversionednumber_la_LDFLAGS = -shared -version-number 1:2:3
tests_version1_libunversionedsymbols_la_LDFLAGS = -shared -version-number 1:0:0
tests_version2_libunversionedsymbols_la_LDFLAGS = -shared -version-number 1:0:0
tests_version1_libversionedabibreak_la_LDFLAGS = -shared -version-number 1:0:0 \
-Wl,--version-script=$(srcdir)/tests/version1/libversionedabibreak.map
tests_version2_libversionedabibreak_la_LDFLAGS = -shared -version-number 1:0:0 \
-Wl,--version-script=$(srcdir)/tests/version2/libversionedabibreak.map
tests_version1_libversionedlikedbus_la_LDFLAGS = -shared -version-number 1:0:0 \
-Wl,--version-script=$(srcdir)/tests/version1/libversionedlikedbus.map
tests_version2_libversionedlikedbus_la_LDFLAGS = -shared -version-number 1:2:0 \
-Wl,--version-script=$(srcdir)/tests/version2/libversionedlikedbus.map
tests_version1_libversionedlikeglibc_la_LDFLAGS = -shared -version-number 1:0:0 \
-Wl,--version-script=$(srcdir)/tests/version1/libversionedlikeglibc.map
tests_version2_libversionedlikeglibc_la_LDFLAGS = -shared -version-number 1:0:0 \
-Wl,--version-script=$(srcdir)/tests/version2/libversionedlikeglibc.map
tests_version1_libversionednumber_la_LDFLAGS = -shared -version-number 1:0:0 \
-Wl,--version-script=$(srcdir)/tests/libversioned.map
tests_version2_libversionednumber_la_LDFLAGS = -shared -version-number 1:2:3 \
-Wl,--version-script=$(srcdir)/tests/libversioned.map
tests_version1_libversionedsymbols_la_LDFLAGS = -shared -version-number 1:0:0 \
-Wl,--version-script=$(srcdir)/tests/libversioned.map
tests_version2_libversionedsymbols_la_LDFLAGS = -shared -version-number 1:0:0 \
-Wl,--version-script=$(srcdir)/tests/libversioned.map
tests_version1_libversionedupgrade_la_LDFLAGS = -shared -version-number 1:0:0 \
-Wl,--version-script=$(srcdir)/tests/version1/libversionedupgrade.map
tests_version2_libversionedupgrade_la_LDFLAGS = -shared -version-number 1:0:0 \
-Wl,--version-script=$(srcdir)/tests/version2/libversionedupgrade.map
endif
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' \
$(SHELL) $(top_srcdir)/build-aux/tap-driver.sh
LOG_COMPILER =
......@@ -476,3 +528,12 @@ EXTRA_DIST += doc/capsule-init-project.xml
EXTRA_DIST += doc/capsule-mkstublib.xml
EXTRA_DIST += doc/devhelp2man.xslt
EXTRA_DIST += tests/glib-tap.sh
EXTRA_DIST += tests/libversioned.map
EXTRA_DIST += tests/version1/libversionedabibreak.map
EXTRA_DIST += tests/version1/libversionedlikedbus.map
EXTRA_DIST += tests/version1/libversionedlikeglibc.map
EXTRA_DIST += tests/version1/libversionedupgrade.map
EXTRA_DIST += tests/version2/libversionedabibreak.map
EXTRA_DIST += tests/version2/libversionedlikedbus.map
EXTRA_DIST += tests/version2/libversionedlikeglibc.map
EXTRA_DIST += tests/version2/libversionedupgrade.map
......@@ -30,9 +30,11 @@ use Test::More;
our @EXPORT = qw(
assert_run_verbose
bind_usr
diag_multiline
explain_wait_status
get_symbols_with_nm
libcapsule_uninstalled
run_ok
run_verbose
skip_all_unless_bwrap
......@@ -336,6 +338,71 @@ sub get_symbols_with_nm {
return sort @symbols_produced;
}
=item bind_usr(I<TREE>[, I<DEST>])
Return B<bwrap>(1) arguments that would bind-mount I<TREE> on I<DEST>.
If I<TREE> has a F<usr> directory, it is assumed to be a complete
sysroot with F<bin>, F<sbin>, F<lib*> and F<usr> directories, which
will be mounted on I<DEST>. If not, it is assumed to be a merged
F</usr>, and will be mounted on I<DEST>F</usr>, with compatibility
symbolic links in I<DEST> for the F<bin>, F<sbin> and F<lib*>
subdirectories.
=cut
sub bind_usr {
my $tree = shift;
my $dest = shift;
$dest = '' unless defined $dest;
my @bwrap;
my $has_usr = (-d "$tree/usr");
if ($has_usr) {
push @bwrap, '--ro-bind', "$tree/usr", "$dest/usr";
}
else {
push @bwrap, '--ro-bind', "$tree", "$dest/usr";
}
opendir(my $dir, $tree);
while (defined(my $subdir = readdir $dir)) {
if ($subdir =~ /^lib/ || $subdir =~ /^s?bin$/) {
if ($has_usr) {
push @bwrap, '--ro-bind', "$tree/$subdir", "$dest/$subdir";
}
else {
push @bwrap, '--symlink', "usr/$subdir", "$dest/$subdir";
}
}
}
closedir $dir;
if (-e "$tree/etc/ld.so.cache") {
push @bwrap, "--ro-bind", "$tree/etc/ld.so.cache",
"$dest/etc/ld.so.cache";
}
# TODO: This wouldn't be necessary in a purely glvnd system
if (-d "$tree/etc/alternatives") {
push @bwrap, "--ro-bind", "$tree/etc/alternatives",
"$dest/etc/alternatives";
}
return @bwrap;
}
=item libcapsule_uninstalled()
Return true if libcapsule is uninstalled (build-time tests) and false
if we are carrying out installed-tests.
=cut
sub libcapsule_uninstalled {
return exists $ENV{CAPSULE_TESTS_UNINSTALLED};
}
=back
=head1 ENVIRONMENT
......
......@@ -31,6 +31,12 @@ use lib $FindBin::Bin;
use CapsuleTest;
sub tolerant_readlink ($)
{
no autodie;
return readlink shift;
}
skip_all_unless_bwrap;
my $LIBDIR = qr{/(?:usr/)?lib(?:32|64|x32)?(?:/\w+-linux-gnu\w*)?(?:/i686)?(?:/cmov)?};
......@@ -39,6 +45,8 @@ my $test_tempdir = File::Temp->newdir();
diag "Working directory: $test_tempdir";
my $host = "${test_tempdir}/host";
mkdir($host);
my $container = "${test_tempdir}/container";
mkdir($container);
my $libdir = "${test_tempdir}/libdir";
run_ok(['rm', '-fr', $libdir]);
......@@ -404,6 +412,115 @@ SKIP: {
ok(! -e "$libdir/libjpeg.so.62");
};
SKIP: {
my $version1 = "$builddir/tests/version1";
$version1 .= '/.libs' if libcapsule_uninstalled;
my $version2 = "$builddir/tests/version2";
$version2 .= '/.libs' if libcapsule_uninstalled;
skip "shared libraries disabled", 1 unless -e "$version1/libunversionedsymbols.so.1";
run_ok(['rm', '-fr', $libdir]);
mkdir($libdir);
$result = run_verbose([qw(bwrap --ro-bind / /),
'--tmpfs', $host,
bind_usr('/', $host),
'--tmpfs', $container,
bind_usr('/', $container),
'--ro-bind', $version1, "$host/opt",
'--ro-bind', $version2, "$container/opt",
'--bind', $libdir, $libdir,
qw(--dev-bind /dev /dev),
'env', 'CAPSULE_DEBUG=all',
$CAPSULE_CAPTURE_LIBS_TOOL, '--link-target=/run/host',
"--dest=$libdir", "--provider=$host",
"--container=$container",
'path-match:/opt/lib*.so.1'],
'2>', \$stderr, '>&2');
diag $stderr;
ok($result);
is(tolerant_readlink("$libdir/libunversionedabibreak.so.1"),
'/run/host/opt/libunversionedabibreak.so.1.0.0',
"should take provider's version when neither's symbols are a superset of the other");
ok(! -l "$libdir/libunversionednumber.so.1",
"should not take provider's version when container's numeric tail is strictly newer");
TODO: {
local $TODO = 'counting symbols not yet implemented';
ok(! -l "$libdir/libunversionedsymbols.so.1",
"should not take provider's version when container has strictly more symbols");
}
is(tolerant_readlink("$libdir/libversionedabibreak.so.1"),
'/run/host/opt/libversionedabibreak.so.1.0.0',
"should take provider's version when neither's symbol-versions are a superset of the other");
ok(! -l "$libdir/libversionedlikedbus.so.1",
"should not take provider's older fake libdbus");
TODO: {
local $TODO = 'comparing versioned symbols not yet implemented';
ok(! -l "$libdir/libversionedlikeglibc.so.1",
"should not take provider's older fake glibc");
}
ok(! -l "$libdir/libversionednumber.so.1",
"should not take provider's version when container's numeric tail is strictly newer and symbols are equal");
TODO: {
local $TODO = 'comparing versioned symbols not yet implemented';
ok(! -l "$libdir/libversionedsymbols.so.1",
"should not take provider's version when container has strictly more symbols");
}
TODO: {
local $TODO = 'comparing versioned symbols not yet implemented';
ok(! -l "$libdir/libversionedupgrade.so.1",
"should not take provider's version when container has strictly more symbols");
}
# The opposite.
run_ok(['rm', '-fr', $libdir]);
mkdir($libdir);
$result = run_verbose([qw(bwrap --ro-bind / /),
'--tmpfs', $host,
bind_usr('/', $host),
'--tmpfs', $container,
bind_usr('/', $container),
'--ro-bind', $version1, "$container/opt",
'--ro-bind', $version2, "$host/opt",
'--bind', $libdir, $libdir,
qw(--dev-bind /dev /dev),
'env', 'CAPSULE_DEBUG=all',
$CAPSULE_CAPTURE_LIBS_TOOL, '--link-target=/run/host',
"--dest=$libdir", "--provider=$host",
"--container=$container",
'path-match:/opt/lib*.so.1'],
'2>', \$stderr, '>&2');
diag $stderr;
ok($result);
is(tolerant_readlink("$libdir/libunversionedabibreak.so.1"),
'/run/host/opt/libunversionedabibreak.so.1.0.0',
"should take provider's version when neither's symbols are a superset of the other");
is(tolerant_readlink("$libdir/libunversionednumber.so.1"),
'/run/host/opt/libunversionednumber.so.1.2.3',
"should take provider's version when container's numeric tail is strictly older");
is(tolerant_readlink("$libdir/libunversionedsymbols.so.1"),
'/run/host/opt/libunversionedsymbols.so.1.0.0',
"should take provider's version when it has strictly more symbols than container");
is(tolerant_readlink("$libdir/libversionedabibreak.so.1"),
'/run/host/opt/libversionedabibreak.so.1.0.0',
"should take provider's version when neither's symbol-versions are a superset of the other");
is(tolerant_readlink("$libdir/libversionedlikedbus.so.1"),
'/run/host/opt/libversionedlikedbus.so.1.2.0',
"should take provider's newer fake libdbus");
is(tolerant_readlink("$libdir/libversionedlikeglibc.so.1"),
'/run/host/opt/libversionedlikeglibc.so.1.0.0',
"should take provider's newer fake glibc");
is(tolerant_readlink("$libdir/libversionednumber.so.1"),
'/run/host/opt/libversionednumber.so.1.2.3',
"should take provider's version when its numeric tail is strictly newer and symbols are equal");
is(tolerant_readlink("$libdir/libversionedsymbols.so.1"),
'/run/host/opt/libversionedsymbols.so.1.0.0',
"should take provider's version when it has strictly more symbols");
is(tolerant_readlink("$libdir/libversionedupgrade.so.1"),
'/run/host/opt/libversionedupgrade.so.1.0.0',
"should take provider's version when it has strictly more symbols");
}
done_testing;
# vim:set sw=4 sts=4 et:
LIBVERSIONED1 {
global:
*;
};
......@@ -297,60 +297,6 @@ my %CAPSULE_CAPTURE_LIBS_TOOLS;
=over
=item bind_usr(I<TREE>[, I<DEST>])
Return B<bwrap>(1) arguments that would bind-mount I<TREE> on I<DEST>.
If I<TREE> has a F<usr> directory, it is assumed to be a complete
sysroot with F<bin>, F<sbin>, F<lib*> and F<usr> directories, which
will be mounted on I<DEST>. If not, it is assumed to be a merged
F</usr>, and will be mounted on I<DEST>F</usr>, with compatibility
symbolic links in I<DEST> for the F<bin>, F<sbin> and F<lib*>
subdirectories.
=cut
sub bind_usr {
my $tree = shift;
my $dest = shift;
$dest = '' unless defined $dest;
my @bwrap;
my $has_usr = (-d "$tree/usr");
if ($has_usr) {
push @bwrap, '--ro-bind', "$tree/usr", "$dest/usr";
}
else {
push @bwrap, '--ro-bind', "$tree", "$dest/usr";
}
opendir(my $dir, $tree);
while (defined(my $subdir = readdir $dir)) {
if ($subdir =~ /^lib/ || $subdir =~ /^s?bin$/) {
if ($has_usr) {
push @bwrap, '--ro-bind', "$tree/$subdir", "$dest/$subdir";
}
else {
push @bwrap, '--symlink', "usr/$subdir", "$dest/$subdir";
}
}
}
closedir $dir;
if (-e "$tree/etc/ld.so.cache") {
push @bwrap, "--ro-bind", "$tree/etc/ld.so.cache",
"$dest/etc/ld.so.cache";
}
# TODO: This wouldn't be necessary in a purely glvnd system
if (-d "$tree/etc/alternatives") {
push @bwrap, "--ro-bind", "$tree/etc/alternatives",
"$dest/etc/alternatives";
}
return @bwrap;
}
=item run_in_container(I<TREE>, I<ARGV>, ...)
Use B<bwrap>(1) to run the command I<ARGV> (an array reference) in I<TREE>,
......
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
LIBVERSIONED1 {
global:
*;
};
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int _private1(int);
int _private1(int x) { return x; }
LIBVERSIONED1 {
global:
symbol*;
};
LIBVERSIONEDPRIVATE_1_0_0 {
global:
_private*;
};
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
LIBVERSIONED1 {
global:
symbol*;
};
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
LIBVERSIONED1 {
global:
*;
};
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol3(int);
int symbol3(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol3(int);
int symbol3(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
LIBVERSIONED2 {
global:
*;
};
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol3(int);
int symbol3(int x) { return x; }
__attribute__((__visibility__("default"))) int _private1(int);
int _private1(int x) { return x; }
LIBVERSIONED1 {
global:
symbol*;
};
LIBVERSIONEDPRIVATE_1_2_0 {
global:
_private*;
};
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__asm__(".symver _original_symbol2,symbol2@LIBVERSIONED1");
__attribute__((__visibility__("default"))) int _original_symbol2(int);
int _original_symbol2(int x) { return x; }
__asm__(".symver symbol2,symbol2@@LIBVERSIONED2");
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x + 1; }
LIBVERSIONED1 {
global:
symbol*;
};
LIBVERSIONED2 {
} LIBVERSIONED1;
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol3(int);
int symbol3(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol1(int);
int symbol1(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol2(int);
int symbol2(int x) { return x; }
__attribute__((__visibility__("default"))) int symbol3(int);
int symbol3(int x) { return x; }
LIBVERSIONED1 {
global:
symbol1;
symbol2;
};
LIBVERSIONED2 {
global:
symbol3;
} LIBVERSIONED1;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment