aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Bachmeyer <jcb@gnu.org>2022-11-30 22:52:25 -0600
committerJacob Bachmeyer <jcb@gnu.org>2022-11-30 22:52:25 -0600
commitcc2dcde3edb178434be6ce74fdd12322a35fcfb5 (patch)
tree008fb21128bf7c744327772e772065cf7b3a0f58
parent25c50aa4235fd396b740f19c5641dea5adaebc27 (diff)
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.
-rw-r--r--ChangeLog13
-rw-r--r--dejagnu.h44
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 <jcb@gnu.org>
+ * 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 <stdio.h>
#include <stdarg.h>
+#include <stdlib.h>
#include <string.h>
/* 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.