From 6f94347e691549b23266073f2bd2e942f1d79901 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 19 May 2016 15:37:17 -0400
Subject: [PATCH 20/35] Makefile.in integration (has a TODO)

Bernd said (in https://gcc.gnu.org/ml/gcc-patches/2015-11/msg01981.html ):
> For some of the simpler infrastructure tests such as the ones in this
> patch kit (bitmap, vec or wide-int functionality testing and such),
> we had the idea of putting these into every ENABLE_CHECKING compiler,
> and run them after building stage1, controlled by a -fself-test flag.
> It's better to detect such basic failures early rather than complete
> a full bootstrap and test cycle. It also keeps the tests alongside the
> rest of the implementation, which I consider desirable for such
> relatively simple data structures."

This patch implements this idea by adding a "selftests" phony target to
gcc/Makefile.in ensuring that the selftests must be successfully run for
the build to complete.
The time taken to run the testsuite is also printed.
A "s-selftests" file is created, so that the selftests need only be run
once each time "cc1" is rebuilt in a working copy.

They are run at each stage in a bootstrap.  For example, looking at a
bootstrap log:

 $ grep "fself-test:" test/experiment/x86_64-pc-linux-gnu/build/make.log
 -fself-test: 576 pass(es); 0 failure(s) in 0.028000 seconds
 -fself-test: 576 pass(es); 0 failure(s) in 0.009000 seconds
 -fself-test: 576 pass(es); 0 failure(s) in 0.011000 seconds

shows that the selftests are indeed run at each stage of a bootstrap,
and that they're fast (well under a second).

There's also a debug target, so that we can type:

  make selftests-gdb

to run the selftests under gdb.

For a release build, the "sorry" in toplev.c leads to an error, and hence
an effective failure.  Changing it to an "inform" fixes this.

TODO: what about build != host?

gcc/ChangeLog:
	* Makefile.in (all.internal): Add "selftests".
	(all.cross): Likewise.
	(selftests): New phony target.
	(s-selftests): New target.
	(selftests-gdb): New phony target.
	* selftest.c (selftest::runner::runner): Initialize m_start_time.
	(selftest::runner::~runner): Print the elapsed time.
	* selftest.h (class selftest::runner): Add field "m_start_time".
	* toplev.c (toplev::run_self_tests): Use "inform" rather than "sorry"
	in an unchecked build.
---
 gcc/Makefile.in | 19 +++++++++++++++++--
 gcc/selftest.c  | 10 +++++++---
 gcc/selftest.h  |  1 +
 gcc/toplev.c    |  2 +-
 4 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index cd44ebb..9f47fb1 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1818,10 +1818,10 @@ config.status: $(srcdir)/configure $(srcdir)/config.gcc
 quickstrap: all
 	cd $(toplevel_builddir) && $(MAKE) all-target-libgcc
 
-all.internal: start.encap rest.encap doc
+all.internal: start.encap rest.encap doc selftests
 # This is what to compile if making a cross-compiler.
 all.cross: native gcc-cross$(exeext) cpp$(exeext) specs \
-	libgcc-support lang.all.cross doc @GENINSRC@ srcextra
+	libgcc-support lang.all.cross doc @GENINSRC@ srcextra selftests
 # This is what must be made before installing GCC and converting libraries.
 start.encap: native xgcc$(exeext) cpp$(exeext) specs \
 	libgcc-support lang.start.encap @GENINSRC@ srcextra
@@ -1841,6 +1841,21 @@ endif
 # This does the things that can't be done on the host machine.
 rest.cross: specs
 
+# Run the selftests during the build once we have a driver and a cc1,
+# so that self-test failures are caught as early as possible.
+# Use "s-selftests" to ensure that we only run the selftests if the
+# driver or cc1 change.
+.PHONY: selftests
+selftests: s-selftests
+s-selftests: xgcc$(exeext) cc1
+	./xgcc$(exeext) -B. -xc -c /dev/null -fself-test
+	$(STAMP) $@
+
+# Convenience method for running selftests under gdb:
+.PHONY: selftests-gdb
+selftests-gdb: xgcc$(exeext) cc1
+	./xgcc$(exeext) -B. -xc -c /dev/null -fself-test -wrapper gdb,--args
+
 # Recompile all the language-independent object files.
 # This is used only if the user explicitly asks for it.
 compilations: $(BACKEND)
diff --git a/gcc/selftest.c b/gcc/selftest.c
index abb6585..af95312 100644
--- a/gcc/selftest.c
+++ b/gcc/selftest.c
@@ -80,7 +80,8 @@ selftest::run_all_tests ()
 
 runner::runner ()
 : m_passes (0),
-  m_failures (0)
+  m_failures (0),
+  m_start_time (get_run_time ())
 {
 }
 
@@ -88,8 +89,11 @@ runner::runner ()
 
 runner::~runner ()
 {
-  fprintf (stderr, "NOTE: %i pass(es); %i failure(s)\n",
-	   m_passes, m_failures);
+  long finish_time = get_run_time ();
+  long elapsed_time = finish_time - m_start_time;
+  fprintf (stderr, "NOTE: %i pass(es); %i failure(s) in %ld.%06ld seconds\n",
+	   m_passes, m_failures,
+	   elapsed_time / 1000000, elapsed_time % 1000000);
 }
 
 /* Notify the user that a particular test is about to be run.  */
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 884bdbf..720e1d5 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -54,6 +54,7 @@ public:
 private:
   int m_passes;
   int m_failures;
+  long m_start_time;
 };
 
 /* The class ::selftest::test is a base class from which specific
diff --git a/gcc/toplev.c b/gcc/toplev.c
index a4b91e9..bb5ac5d 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -2077,7 +2077,7 @@ toplev::run_self_tests ()
   /* Cleanup.  */
   bitmap_obstack_release (NULL);
 #else
-  sorry ("self-tests are not enabled in this build");
+  inform (UNKNOWN_LOCATION, "self-tests are not enabled in this build");
 #endif /* #if CHECKING_P */
 }
 
-- 
1.8.5.3

