8a8cfb
commit 561b0bec4448f0302cb4915bf67c919bde4a1c57
8a8cfb
Author: DJ Delorie <dj@redhat.com>
8a8cfb
Date:   Fri Jul 6 01:10:41 2018 -0400
8a8cfb
8a8cfb
    Add test-in-container infrastructure.
8a8cfb
    
8a8cfb
    * Makefile (testroot.pristine): New rules to initialize the
8a8cfb
    test-in-container "testroot".
8a8cfb
    * Makerules (all-testsuite): Add tests-container.
8a8cfb
    * Rules (tests-expected): Add tests-container.
8a8cfb
    (binaries-all-tests): Likewise.
8a8cfb
    (tests-container): New, run these tests in the testroot container.
8a8cfb
    * support/links-dso-program-c.c: New.
8a8cfb
    * support/links-dso-program.cc: New.
8a8cfb
    * support/test-container.c: New.
8a8cfb
    * support/shell-container.c: New.
8a8cfb
    * support/echo-container.c: New.
8a8cfb
    * support/true-container.c: New.
8a8cfb
    * support/xmkdirp.c: New.
8a8cfb
    * support/xsymlink.c: New.
8a8cfb
    * support/support_paths.c: New.
8a8cfb
    * support/support.h: Add support paths prototypes.
8a8cfb
    * support/xunistd.h: Add xmkdirp () and xsymlink ().
8a8cfb
    
8a8cfb
    * nss/tst-nss-test3.c: Convert to test-in-container.
8a8cfb
    * nss/tst-nss-test3.root/: New.
8a8cfb
8a8cfb
(note: support/ already present, not needed; sample test not included)
8a8cfb
8a8cfb
diff --git a/Makefile b/Makefile
8a8cfb
index d3f25a5..3df55e6 100644
8a8cfb
--- a/Makefile
8a8cfb
+++ b/Makefile
8a8cfb
@@ -340,6 +340,62 @@ define summarize-tests
8a8cfb
 @! egrep -q -v '^(X?PASS|XFAIL|UNSUPPORTED):' $(objpfx)$1
8a8cfb
 endef
8a8cfb
 
8a8cfb
+# The intention here is to do ONE install of our build into the
8a8cfb
+# testroot.pristine/ directory, then rsync (internal to
8a8cfb
+# support/test-container) that to testroot.root/ at the start of each
8a8cfb
+# test.  That way we can promise each test a "clean" install, without
8a8cfb
+# having to do the install for each test.
8a8cfb
+#
8a8cfb
+# In addition, we have to copy some files (which we build) into this
8a8cfb
+# root in addition to what glibc installs.  For example, many tests
8a8cfb
+# require additional programs including /bin/sh, /bin/true, and
8a8cfb
+# /bin/echo, all of which we build below to limit library dependencies
8a8cfb
+# to just those things in glibc and language support libraries which
8a8cfb
+# we also copy into the into the rootfs.  To determine what language
8a8cfb
+# support libraries we need we build a "test" program in either C or
8a8cfb
+# (if available) C++ just so we can copy in any shared objects
8a8cfb
+# (which we do not build) that GCC-compiled programs depend on.
8a8cfb
+
8a8cfb
+
8a8cfb
+ifeq (,$(CXX))
8a8cfb
+LINKS_DSO_PROGRAM = links-dso-program-c
8a8cfb
+else
8a8cfb
+LINKS_DSO_PROGRAM = links-dso-program
8a8cfb
+endif
8a8cfb
+
8a8cfb
+$(tests-container) $(addsuffix /tests,$(subdirs)) : \
8a8cfb
+		$(objpfx)testroot.pristine/install.stamp
8a8cfb
+$(objpfx)testroot.pristine/install.stamp :
8a8cfb
+	test -d $(objpfx)testroot.pristine || \
8a8cfb
+	  mkdir $(objpfx)testroot.pristine
8a8cfb
+	# We need a working /bin/sh for some of the tests.
8a8cfb
+	test -d $(objpfx)testroot.pristine/bin || \
8a8cfb
+	  mkdir $(objpfx)testroot.pristine/bin
8a8cfb
+	cp $(objpfx)support/shell-container $(objpfx)testroot.pristine/bin/sh
8a8cfb
+	cp $(objpfx)support/echo-container $(objpfx)testroot.pristine/bin/echo
8a8cfb
+	cp $(objpfx)support/true-container $(objpfx)testroot.pristine/bin/true
8a8cfb
+	# Copy these DSOs first so we can overwrite them with our own.
8a8cfb
+	for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1  \
8a8cfb
+		$(objpfx)elf/$(rtld-installed-name) \
8a8cfb
+		$(objpfx)testroot.pristine/bin/sh \
8a8cfb
+	        | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\
8a8cfb
+	  do \
8a8cfb
+	    test -d `dirname $(objpfx)testroot.pristine$$dso` || \
8a8cfb
+	      mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\
8a8cfb
+	    $(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\
8a8cfb
+	  done
8a8cfb
+	for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1  \
8a8cfb
+		$(objpfx)elf/$(rtld-installed-name) \
8a8cfb
+		$(objpfx)support/$(LINKS_DSO_PROGRAM) \
8a8cfb
+	        | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\
8a8cfb
+	  do \
8a8cfb
+	    test -d `dirname $(objpfx)testroot.pristine$$dso` || \
8a8cfb
+	      mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\
8a8cfb
+	    $(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\
8a8cfb
+	  done
8a8cfb
+	$(MAKE) install DESTDIR=$(objpfx)testroot.pristine
8a8cfb
+	touch $(objpfx)testroot.pristine/install.stamp
8a8cfb
+
8a8cfb
 tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special))
8a8cfb
 tests: $(tests-special)
8a8cfb
 	$(..)scripts/merge-test-results.sh -s $(objpfx) "" \
8a8cfb
diff --git a/Makerules b/Makerules
8a8cfb
index a10a0b4..5d6434c 100644
8a8cfb
--- a/Makerules
8a8cfb
+++ b/Makerules
8a8cfb
@@ -1369,7 +1369,8 @@ xcheck: xtests
8a8cfb
 # The only difference between MODULE_NAME=testsuite and MODULE_NAME=nonlib is
8a8cfb
 # that almost all internal declarations from config.h, libc-symbols.h, and
8a8cfb
 # include/*.h are not available to 'testsuite' code, but are to 'nonlib' code.
8a8cfb
-all-testsuite := $(strip $(tests) $(xtests) $(test-srcs) $(test-extras))
8a8cfb
+all-testsuite := $(strip $(tests) $(xtests) $(test-srcs) $(test-extras) \
8a8cfb
+		 $(tests-container))
8a8cfb
 ifneq (,$(all-testsuite))
8a8cfb
 cpp-srcs-left = $(all-testsuite)
8a8cfb
 lib := testsuite
8a8cfb
diff --git a/Rules b/Rules
8a8cfb
index 706c8a7..5abb727 100644
8a8cfb
--- a/Rules
8a8cfb
+++ b/Rules
8a8cfb
@@ -130,12 +130,14 @@ others: $(py-const)
8a8cfb
 
8a8cfb
 ifeq ($(run-built-tests),no)
8a8cfb
 tests: $(addprefix $(objpfx),$(filter-out $(tests-unsupported), \
8a8cfb
-                                          $(tests) $(tests-internal)) \
8a8cfb
+                                          $(tests) $(tests-internal) \
8a8cfb
+					  $(tests-container)) \
8a8cfb
 			     $(test-srcs)) $(tests-special) \
8a8cfb
 			     $(tests-printers-programs)
8a8cfb
 xtests: tests $(xtests-special)
8a8cfb
 else
8a8cfb
 tests: $(tests:%=$(objpfx)%.out) $(tests-internal:%=$(objpfx)%.out) \
8a8cfb
+       $(tests-container:%=$(objpfx)%.out) \
8a8cfb
        $(tests-special) $(tests-printers-out)
8a8cfb
 xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-special)
8a8cfb
 endif
8a8cfb
@@ -145,7 +147,8 @@ xtests-special-notdir = $(patsubst $(objpfx)%, %, $(xtests-special))
8a8cfb
 ifeq ($(run-built-tests),no)
8a8cfb
 tests-expected =
8a8cfb
 else
8a8cfb
-tests-expected = $(tests) $(tests-internal) $(tests-printers)
8a8cfb
+tests-expected = $(tests) $(tests-internal) $(tests-printers) \
8a8cfb
+	$(tests-container)
8a8cfb
 endif
8a8cfb
 tests:
8a8cfb
 	$(..)scripts/merge-test-results.sh -s $(objpfx) $(subdir) \
8a8cfb
@@ -158,7 +161,8 @@ xtests:
8a8cfb
 
8a8cfb
 ifeq ($(build-programs),yes)
8a8cfb
 binaries-all-notests = $(others) $(sysdep-others)
8a8cfb
-binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs)
8a8cfb
+binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs) \
8a8cfb
+		     $(tests-container)
8a8cfb
 binaries-all = $(binaries-all-notests) $(binaries-all-tests)
8a8cfb
 binaries-static-notests = $(others-static)
8a8cfb
 binaries-static-tests = $(tests-static) $(xtests-static)
8a8cfb
@@ -248,6 +252,17 @@ $(objpfx)%.out: /dev/null $(objpfx)%	# Make it 2nd arg for canned sequence.
8a8cfb
 	$(make-test-out) > $@; \
8a8cfb
 	$(evaluate-test)
8a8cfb
 
8a8cfb
+
8a8cfb
+# Any tests that require an isolated container (filesystem, network
8a8cfb
+# and pid namespaces) in which to run, should be added to
8a8cfb
+# tests-container.
8a8cfb
+$(tests-container:%=$(objpfx)%.out): $(objpfx)%.out : $(if $(wildcard $(objpfx)%.files),$(objpfx)%.files,/dev/null) $(objpfx)%
8a8cfb
+	$(test-wrapper-env) $(run-program-env) $(run-via-rtld-prefix) \
8a8cfb
+	  $(common-objpfx)support/test-container env $(run-program-env) $($*-ENV) \
8a8cfb
+	  $(host-test-program-cmd) $($*-ARGS) > $@; \
8a8cfb
+	$(evaluate-test)
8a8cfb
+
8a8cfb
+
8a8cfb
 # tests-unsupported lists tests that we will not try to build at all in
8a8cfb
 # this configuration.  Note this runs every time because it does not
8a8cfb
 # actually create its target.  The dependency on Makefile is meant to