mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-21 03:26:01 +00:00
Run startup unit tests from Main
This commit is contained in:
@@ -110,6 +110,8 @@
|
|||||||
#define BEAST_BOOST_IS_AVAILABLE 0
|
#define BEAST_BOOST_IS_AVAILABLE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Bind source configuration.
|
/** Bind source configuration.
|
||||||
|
|
||||||
Set one of these to manually force a particular implementation of bind().
|
Set one of these to manually force a particular implementation of bind().
|
||||||
|
|||||||
@@ -141,6 +141,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
struct Suite
|
struct Suite
|
||||||
{
|
{
|
||||||
|
String className;
|
||||||
|
String packageName;
|
||||||
|
Time whenStarted;
|
||||||
|
double secondsElapsed;
|
||||||
|
int tests;
|
||||||
|
int failures;
|
||||||
|
OwnedArray <Case, CriticalSection> cases;
|
||||||
|
|
||||||
|
//----
|
||||||
|
|
||||||
Suite (String const& className_, String const& packageName_)
|
Suite (String const& className_, String const& packageName_)
|
||||||
: className (className_)
|
: className (className_)
|
||||||
, packageName (packageName_)
|
, packageName (packageName_)
|
||||||
@@ -151,13 +161,13 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
String className;
|
// for convenience
|
||||||
String packageName;
|
String getSuiteName () const noexcept
|
||||||
Time whenStarted;
|
{
|
||||||
double secondsElapsed;
|
String s;
|
||||||
int tests;
|
s << packageName << "::" << className;
|
||||||
int failures;
|
return s;
|
||||||
OwnedArray <Case, CriticalSection> cases;
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The type of a list of tests.
|
/** The type of a list of tests.
|
||||||
|
|||||||
@@ -17,8 +17,103 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
Main::Main (int argc, char const* const* argv)
|
Static::Storage <Atomic <Main*>, Main> Main::s_instance;
|
||||||
: m_argc (argc)
|
|
||||||
, m_argv (argv)
|
Main::Main ()
|
||||||
{
|
{
|
||||||
|
bool const replaced = s_instance->compareAndSetBool (this, nullptr);
|
||||||
|
|
||||||
|
// If this happens it means there are two instances of Main!
|
||||||
|
if (! replaced)
|
||||||
|
FatalError ("Multiple instances of Main", __FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
Main::~Main ()
|
||||||
|
{
|
||||||
|
s_instance->set (nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Main& Main::getInstance ()
|
||||||
|
{
|
||||||
|
bassert (s_instance->get () != nullptr);
|
||||||
|
|
||||||
|
return *s_instance->get ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Main::runStartupUnitTests ()
|
||||||
|
{
|
||||||
|
struct StartupUnitTests : UnitTests
|
||||||
|
{
|
||||||
|
void logMessage (String const&)
|
||||||
|
{
|
||||||
|
// Intentionally do nothing, we don't want
|
||||||
|
// to see the extra output for startup tests.
|
||||||
|
}
|
||||||
|
|
||||||
|
void log (String const& message)
|
||||||
|
{
|
||||||
|
#if BEAST_MSVC
|
||||||
|
if (beast_isRunningUnderDebugger ())
|
||||||
|
Logger::outputDebugString (message);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::cerr << message.toStdString () << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reportCase (String const& suiteName, UnitTest::Case const& testcase)
|
||||||
|
{
|
||||||
|
String s;
|
||||||
|
s << suiteName << " (" << testcase.name << ") produced " <<
|
||||||
|
String (testcase.failures) <<
|
||||||
|
((testcase.failures == 1) ? " failure." : " failures.");
|
||||||
|
log (s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reportSuite (UnitTest::Suite const& suite)
|
||||||
|
{
|
||||||
|
if (suite.failures > 0)
|
||||||
|
{
|
||||||
|
String const suiteName = suite.getSuiteName ();
|
||||||
|
|
||||||
|
for (int i = 0; i < suite.cases.size (); ++i)
|
||||||
|
{
|
||||||
|
UnitTest::Case const& testcase (*suite.cases [i]);
|
||||||
|
|
||||||
|
if (testcase.failures > 0)
|
||||||
|
reportCase (suiteName, testcase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reportSuites (UnitTests::Results const& results)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < results.suites.size (); ++i)
|
||||||
|
reportSuite (*results.suites [i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reportResults ()
|
||||||
|
{
|
||||||
|
reportSuites (getResults ());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
StartupUnitTests tests;
|
||||||
|
|
||||||
|
tests.runStartupTests ();
|
||||||
|
|
||||||
|
if (tests.anyTestsFailed ())
|
||||||
|
{
|
||||||
|
tests.reportResults ();
|
||||||
|
|
||||||
|
tests.log ("Terminating due to failed startup tests");
|
||||||
|
|
||||||
|
Process::terminate ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Main::runFromMain (int argc, char const* const* argv)
|
||||||
|
{
|
||||||
|
runStartupUnitTests ();
|
||||||
|
|
||||||
|
return run (argc, argv);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,19 +21,59 @@
|
|||||||
#define BEAST_MAIN_H_INCLUDED
|
#define BEAST_MAIN_H_INCLUDED
|
||||||
|
|
||||||
/** Represents a command line program's entry point.
|
/** Represents a command line program's entry point.
|
||||||
|
|
||||||
|
To use this, derive your class from @ref Main and implement the
|
||||||
|
function run ();
|
||||||
*/
|
*/
|
||||||
class BEAST_API Main : Uncopyable
|
class BEAST_API Main : Uncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Main (int argc, char const* const* argv);
|
Main ();
|
||||||
|
|
||||||
int getExitCode () const;
|
virtual ~Main ();
|
||||||
|
|
||||||
|
/** Run the program.
|
||||||
|
|
||||||
|
You should call this from your @ref main function. Don't put
|
||||||
|
anything else in there. Instead, do it in your class derived
|
||||||
|
from Main. For example:
|
||||||
|
|
||||||
|
@code
|
||||||
|
|
||||||
|
struct MyProgram : Main
|
||||||
|
{
|
||||||
|
int run (int argc, char const* const* argv)
|
||||||
|
{
|
||||||
|
std::cout << "Hello, world!" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main (int argc, char const* const* argv)
|
||||||
|
{
|
||||||
|
MyProgram program;
|
||||||
|
|
||||||
|
return program.runFromMain (argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
int runFromMain (int argc, char const* const* argv);
|
||||||
|
|
||||||
|
/** Retrieve the instance of the program. */
|
||||||
static Main& getInstance ();
|
static Main& getInstance ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int const m_argc;
|
/** Entry point for running the program.
|
||||||
char const* const* const m_argv;
|
Subclasses provide the implementation.
|
||||||
|
*/
|
||||||
|
virtual int run (int argc, char const* const* argv) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void runStartupUnitTests ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Static::Storage <Atomic <Main*>, Main> s_instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user