From cc2dcde3edb178434be6ce74fdd12322a35fcfb5 Mon Sep 17 00:00:00 2001 From: Jacob Bachmeyer Date: Wed, 30 Nov 2022 22:52:25 -0600 Subject: Revise generation of "END" messages in dejagnu.h The "END" message is now produced upon normal exit, without requiring that the totals() function or method be called. The C++ API now emits totals only when the last TestState object in the program is destroyed, instead of every time a TestState object is destroyed. This required adding code to track the number of live TestState objects. --- ChangeLog | 13 +++++++++++++ dejagnu.h | 44 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 128bf52..27d1b57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ 2022-11-30 Jacob Bachmeyer + * dejagnu.h (DG__endmsg): New function, called using atexit(). + (endmsg_registered, TestState_count): Add fields to DG__status. + (DG__init): New function, to register DG__endmsg. + (pass, xpass, fail, xfail, untested, unresolved, unsupported) + (note): Call DG__init to ensure libdejagnu initialization. + (totals): Move "END" message to DG__endmsg. + (TestState::TestState): Consider DG__endmsg registered when a + TestState object is constructed. + (TestState::TestState, TestState::~TestState): Track number of + live TestState objects in global status structure. + (TestState::~TestState): Call totals() and emit "END" message only + when the last TestState object is destroyed. + * dejagnu.h (outstate): Remove. (TestState::pass, TestState::xpass, TestState::fail) (TestState::xfail, TestState::untested, TestState::unresolved) diff --git a/dejagnu.h b/dejagnu.h index 2541464..920ff69 100644 --- a/dejagnu.h +++ b/dejagnu.h @@ -22,6 +22,7 @@ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include +#include #include /* If you have problems with DejaGnu dropping failed, untested, or @@ -38,14 +39,31 @@ static struct { int untested; int unresolved; int unsupported; + /**/ + int endmsg_registered; + int TestState_count; /* number of live TestState objects in C++ */ } DG__status = { 0 }; +static inline void +DG__endmsg (void) +{ puts ("\tEND: done"); } + +static inline void +DG__init (void) +{ + if (DG__status.endmsg_registered) return; + + if (atexit (DG__endmsg) == 0) + DG__status.endmsg_registered = 1; +} + static inline void pass (const char* fmt, ...) { va_list ap; DG__status.pass++; + DG__init (); flockfile (stdout); fputs ("\tPASSED: ", stdout); @@ -60,6 +78,7 @@ xpass (const char* fmt, ...) va_list ap; DG__status.xpass++; + DG__init (); flockfile (stdout); fputs ("\tXPASSED: ", stdout); @@ -74,6 +93,7 @@ fail (const char* fmt, ...) va_list ap; DG__status.fail++; + DG__init (); flockfile (stdout); fputs ("\tFAILED: ", stdout); @@ -88,6 +108,7 @@ xfail (const char* fmt, ...) va_list ap; DG__status.xfail++; + DG__init (); flockfile (stdout); fputs ("\tXFAILED: ", stdout); @@ -102,6 +123,7 @@ untested (const char* fmt, ...) va_list ap; DG__status.untested++; + DG__init (); flockfile (stdout); fputs ("\tUNTESTED: ", stdout); @@ -116,6 +138,7 @@ unresolved (const char* fmt, ...) va_list ap; DG__status.unresolved++; + DG__init (); flockfile (stdout); fputs ("\tUNRESOLVED: ", stdout); @@ -130,6 +153,7 @@ unsupported (const char* fmt, ...) va_list ap; DG__status.unsupported++; + DG__init (); flockfile (stdout); fputs ("\tUNSUPPORTED: ", stdout); @@ -143,6 +167,8 @@ note (const char* fmt, ...) { va_list ap; + DG__init (); + flockfile (stdout); fputs ("\tNOTE: ", stdout); va_start (ap, fmt); vfprintf (stdout, fmt, ap); va_end (ap); @@ -166,7 +192,6 @@ totals (void) printf ("\t#unresolved:\t\t%d\n", DG__status.unresolved); if (DG__status.unsupported) printf ("\t#unsupported:\t\t%d\n", DG__status.unsupported); - printf ("\tEND: done\n"); } #ifdef __cplusplus @@ -200,9 +225,22 @@ class TestState { DG__status.untested = 0; DG__status.unresolved = 0; DG__status.unsupported = 0; + + /* C++ object destruction will substitute for atexit(). */ + DG__status.endmsg_registered = 1; + DG__status.TestState_count++; } - ~TestState (void) { totals(); } + ~TestState (void) + { + DG__status.TestState_count--; + + if (DG__status.TestState_count > 0) return; + + /* The last TestState object is being destroyed. */ + totals (); + std::cout << "\tEND: done" << std::endl; + } void testrun (bool b, std::string s) { @@ -297,8 +335,6 @@ class TestState { if (DG__status.unsupported) std::cout << "\t#unsupported:\t\t" << DG__status.unsupported << std::endl; - - std::cout << "\tEND: done" << std::endl; } // This is so this class can be printed in an ostream. -- cgit v1.2.3