summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorAaron Terrell (Enus) <enus@lindenlab.com>2010-08-24 15:15:14 -0700
committerAaron Terrell (Enus) <enus@lindenlab.com>2010-08-24 15:15:14 -0700
commitee5a71be1091a4d71486fa5f7af1099c763684f2 (patch)
tree73fa9cfbb6ad61973d024ed57a694c5ee00eae75 /indra
parent98cc2365034a93c69704daa69efb389799cc9627 (diff)
clean commit of teamcity service message related changes of unit test reporting into a clean repo
Diffstat (limited to 'indra')
-rw-r--r--indra/test/test.cpp638
1 files changed, 509 insertions, 129 deletions
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 57797f9d9f..d6959a2662 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -56,62 +56,75 @@
namespace tut
{
std::string sSourceDir;
-
+
test_runner_singleton runner;
}
class LLTestCallback : public tut::callback
{
public:
- LLTestCallback(bool verbose_mode, std::ostream *stream) :
- mVerboseMode(verbose_mode),
- mTotalTests(0),
- mPassedTests(0),
- mFailedTests(0),
- mSkippedTests(0),
- mStream(stream)
+ LLTestCallback(bool verbose_mode, std::ostream *stream, std::string suitename) :
+ mVerboseMode(verbose_mode),
+ mTotalTests(0),
+ mPassedTests(0),
+ mFailedTests(0),
+ mSkippedTests(0),
+ mStream(stream),
+ suite_name(suitename)
{
}
-
- void run_started()
+
+ LLTestCallback()
+ {
+ }
+
+ virtual void run_started()
{
//std::cout << "run_started" << std::endl;
}
-
- void test_completed(const tut::test_result& tr)
+
+ virtual void group_started(const std::string& name) {
+ std::cout << "group_started name=" << name << std::endl;
+ }
+
+ virtual void group_completed(const std::string& name) {
+ std::cout << "group_completed name=" << name << std::endl;
+ }
+
+ virtual void test_completed(const tut::test_result& tr)
{
++mTotalTests;
std::ostringstream out;
out << "[" << tr.group << ", " << tr.test << "] ";
switch(tr.result)
{
- case tut::test_result::ok:
- ++mPassedTests;
- out << "ok";
- break;
- case tut::test_result::fail:
- ++mFailedTests;
- out << "fail";
- break;
- case tut::test_result::ex:
- ++mFailedTests;
- out << "exception";
- break;
- case tut::test_result::warn:
- ++mFailedTests;
- out << "test destructor throw";
- break;
- case tut::test_result::term:
- ++mFailedTests;
- out << "abnormal termination";
- break;
- case tut::test_result::skip:
- ++mSkippedTests;
- out << "skipped known failure";
- break;
- default:
- ++mFailedTests;
- out << "unknown";
+ case tut::test_result::ok:
+ ++mPassedTests;
+ out << "ok";
+ break;
+ case tut::test_result::fail:
+ ++mFailedTests;
+ out << "fail";
+ break;
+ case tut::test_result::ex:
+ ++mFailedTests;
+ out << "exception";
+ break;
+ case tut::test_result::warn:
+ ++mFailedTests;
+ out << "test destructor throw";
+ break;
+ case tut::test_result::term:
+ ++mFailedTests;
+ out << "abnormal termination";
+ break;
+ case tut::test_result::skip:
+ ++mSkippedTests;
+ out << "skipped known failure";
+ break;
+ default:
+ ++mFailedTests;
+ out << "unknown";
}
if(mVerboseMode || (tr.result != tut::test_result::ok))
{
@@ -127,8 +140,8 @@ public:
std::cout << out.str() << std::endl;
}
}
-
- void run_completed()
+
+ virtual void run_completed()
{
if (mStream)
{
@@ -136,11 +149,11 @@ public:
}
run_completed_(std::cout);
}
-
- int getFailedTests() const { return mFailedTests; }
-private:
- void run_completed_(std::ostream &stream)
+ virtual int getFailedTests() const { return mFailedTests; }
+
+ //private:
+ virtual void run_completed_(std::ostream &stream)
{
stream << "\tTotal Tests:\t" << mTotalTests << std::endl;
stream << "\tPassed Tests:\t" << mPassedTests;
@@ -149,13 +162,13 @@ private:
stream << "\tYAY!! \\o/";
}
stream << std::endl;
-
+
if (mSkippedTests > 0)
{
stream << "\tSkipped known failures:\t" << mSkippedTests
- << std::endl;
+ << std::endl;
}
-
+
if(mFailedTests > 0)
{
stream << "*********************************" << std::endl;
@@ -164,8 +177,161 @@ private:
stream << "*********************************" << std::endl;
}
}
+
+protected:
+ std::string suite_name;
+ bool mVerboseMode;
+ int mTotalTests;
+ int mPassedTests;
+ int mFailedTests;
+ int mSkippedTests;
+ std::ostream *mStream;
+};
+
+// copy of LLTestCallback which should become a subclass (commented out below). Delete this LLTCTestCallback one fixed.
+// TeamCity specific class which emits service messages
+// http://confluence.jetbrains.net/display/TCD3/Build+Script+Interaction+with+TeamCity;#BuildScriptInteractionwithTeamCity-testReporting
+
+class LLTCTestCallback : public tut::callback
+{
+public:
+ LLTCTestCallback(bool verbose_mode, std::ostream *stream, std::string suitename) :
+ mVerboseMode(verbose_mode),
+ mTotalTests(0),
+ mPassedTests(0),
+ mFailedTests(0),
+ mSkippedTests(0),
+ mStream(stream),
+ suite_name(suitename)
+ {
+ }
+
+ LLTCTestCallback()
+ {
+ }
+
+ virtual void run_started()
+ {
+ //std::cout << "unit test run_started" << std::flush;
+ }
+
+ virtual void group_started(const std::string& name) {
+ std::cout << "group_started name=" << name << std::endl;
+ std::cout << "##teamcity[testSuiteStarted name='" << name << "']\n" << std::flush;
+ }
+
+ virtual void group_completed(const std::string& name) {
+ std::cout << "group_completed name=" << name << std::endl;
+ std::cout << "##teamcity[testSuiteFinished name='" << name << "']\n" << std::flush;
+ }
+
+ virtual void test_completed(const tut::test_result& tr)
+ {
+ ++mTotalTests;
+ std::ostringstream out;
+ out << "[" << tr.group << ", " << tr.test << "] \n";
+ switch(tr.result)
+ {
+ case tut::test_result::ok:
+ ++mPassedTests;
+ out << "ok";
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ case tut::test_result::fail:
+ ++mFailedTests;
+ out << "fail";
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ case tut::test_result::ex:
+ ++mFailedTests;
+ out << "exception";
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ case tut::test_result::warn:
+ ++mFailedTests;
+ out << "test destructor throw";
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ case tut::test_result::term:
+ ++mFailedTests;
+ out << "abnormal termination";
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ case tut::test_result::skip:
+ ++mSkippedTests;
+ out << "skipped known failure";
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testIgnored name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ default:
+ ++mFailedTests;
+ out << "unknown";
+ }
+ if(mVerboseMode || (tr.result != tut::test_result::ok))
+ {
+ if(!tr.message.empty())
+ {
+ out << ": '" << tr.message << "'";
+ }
+ if (mStream)
+ {
+ *mStream << out.str() << std::endl;
+ }
+
+ std::cout << out.str() << std::endl;
+ }
+ }
+
+ virtual void run_completed()
+ {
+ if (mStream)
+ {
+ run_completed_(*mStream);
+ }
+ run_completed_(std::cout);
+ }
+
+ virtual int getFailedTests() const { return mFailedTests; }
+
+ //private:
+ virtual void run_completed_(std::ostream &stream)
+ {
+ stream << "\tTotal Tests:\t" << mTotalTests << std::endl;
+ stream << "\tPassed Tests:\t" << mPassedTests;
+ if (mPassedTests == mTotalTests)
+ {
+ stream << "\tYAY!! \\o/";
+ }
+ stream << std::endl;
+
+ if (mSkippedTests > 0)
+ {
+ stream << "\tSkipped known failures:\t" << mSkippedTests
+ << std::endl;
+ }
+
+ if(mFailedTests > 0)
+ {
+ stream << "*********************************" << std::endl;
+ stream << "Failed Tests:\t" << mFailedTests << std::endl;
+ stream << "Please report or fix the problem." << std::endl;
+ stream << "*********************************" << std::endl;
+ }
+ }
+
protected:
+ std::string suite_name;
bool mVerboseMode;
int mTotalTests;
int mPassedTests;
@@ -174,6 +340,107 @@ protected:
std::ostream *mStream;
};
+
+/*
+ // commented out subclass which should be fixed to eliminate the duplicated LLTestCallback and LLTCTestCallaback classes
+ // when this is fixed, the duplicated code in the if(getenv("TEAMCITY_PROJECT_NAME") statements below
+ //
+ // currectly producing errors like thr following:
+ // {path}viewer-tut-teamcity2/indra/build-darwin-i386/sharedlibs/RelWithDebInfo/RelWithDebInfo/PROJECT_llmessage_TEST_llmime
+ // --touch={path}viewer-tut-teamcity2/indra/build-darwin-i386/llmessage/PROJECT_llmessage_TEST_llmime_ok.txt
+ // --{path}viewer-tut-teamcity2/indra/llmessage
+ //
+ // run_started
+ // group_started name=mime_index
+ // ##teamcity[testSuiteStarted name='mime_index']
+ // Segmentation fault
+
+
+ // TeamCity specific class which emits service messages
+ // http://confluence.jetbrains.net/display/TCD3/Build+Script+Interaction+with+TeamCity;#BuildScriptInteractionwithTeamCity-testReporting
+
+ class LLTCTestCallback : public LLTestCallback
+ {
+ public:
+ LLTCTestCallback(bool verbose_mode, std::ostream *stream, std::string suitename) :
+ mVerboseMode(verbose_mode),
+ mTotalTests(0),
+ mPassedTests(0),
+ mFailedTests(0),
+ mSkippedTests(0),
+ mStream(stream),
+ suite_name(suitename)
+ {
+ }
+
+ LLTCTestCallback()
+ {
+ }
+
+ virtual void group_started(const std::string& name) {
+ LLTestCallback::group_started(name);
+ std::cout << "##teamcity[testSuiteStarted name='" << name << "']\n" << std::flush;
+ }
+
+ virtual void group_completed(const std::string& name) {
+ LLTestCallback::group_completed(name);
+ std::cout << "##teamcity[testSuiteFinished name='" << name << "']\n" << std::flush;
+ }
+
+ virtual void test_completed(const tut::test_result& tr)
+ {
+ LLTestCallback::test_completed(tr);
+
+ switch(tr.result)
+ {
+ case tut::test_result::ok:
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ case tut::test_result::fail:
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ case tut::test_result::ex:
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ case tut::test_result::warn:
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ case tut::test_result::term:
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ case tut::test_result::skip:
+ std::cout << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testIgnored name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ std::cout << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']\n" << std::flush;
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ protected:
+ std::string suite_name;
+ bool mVerboseMode;
+ int mTotalTests;
+ int mPassedTests;
+ int mFailedTests;
+ int mSkippedTests;
+ std::ostream *mStream;
+ };
+
+ }
+ */
+
static const apr_getopt_option_t TEST_CL_OPTIONS[] =
{
{"help", 'h', 0, "Print the help message."},
@@ -185,27 +452,28 @@ static const apr_getopt_option_t TEST_CL_OPTIONS[] =
{"touch", 't', 1, "Touch the given file if all tests succeed"},
{"wait", 'w', 0, "Wait for input before exit."},
{"debug", 'd', 0, "Emit full debug logs."},
+ {"suitename", 'x', 1, "Run tests using this suitename"},
{0, 0, 0, 0}
};
void stream_usage(std::ostream& s, const char* app)
{
s << "Usage: " << app << " [OPTIONS]" << std::endl
- << std::endl;
-
+ << std::endl;
+
s << "This application runs the unit tests." << std::endl << std::endl;
-
+
s << "Options: " << std::endl;
const apr_getopt_option_t* option = &TEST_CL_OPTIONS[0];
while(option->name)
{
s << " ";
s << " -" << (char)option->optch << ", --" << option->name
- << std::endl;
+ << std::endl;
s << "\t" << option->description << std::endl << std::endl;
++option;
}
-
+
s << "Examples:" << std::endl;
s << " " << app << " --verbose" << std::endl;
s << "\tRun all the tests and report all results." << std::endl;
@@ -242,13 +510,13 @@ int main(int argc, char **argv)
LLError::initForApplication(".");
LLError::setFatalFunction(wouldHaveCrashed);
LLError::setDefaultLevel(LLError::LEVEL_ERROR);
- //< *TODO: should come from error config file. Note that we
- // have a command line option that sets this to debug.
+ //< *TODO: should come from error config file. Note that we
+ // have a command line option that sets this to debug.
#ifdef CTYPE_WORKAROUND
ctype_workaround();
#endif
-
+
apr_initialize();
apr_pool_t* pool = NULL;
if(APR_SUCCESS != apr_pool_create(&pool, NULL))
@@ -262,12 +530,13 @@ int main(int argc, char **argv)
std::cerr << "Unable to pool" << std::endl;
return 1;
}
-
+
// values used for controlling application
bool verbose_mode = false;
bool wait_at_exit = false;
std::string test_group;
-
+ std::string suite_name;
+
// values use for options parsing
apr_status_t apr_err;
const char* opt_arg = NULL;
@@ -283,88 +552,199 @@ int main(int argc, char **argv)
{
char buf[255]; /* Flawfinder: ignore */
std::cerr << "Error parsing options: "
- << apr_strerror(apr_err, buf, 255) << std::endl;
+ << apr_strerror(apr_err, buf, 255) << std::endl;
return 1;
}
switch (opt_id)
{
- case 'g':
- test_group.assign(opt_arg);
- break;
- case 'h':
- stream_usage(std::cout, argv[0]);
- return 0;
- break;
- case 'l':
- stream_groups(std::cout, argv[0]);
- return 0;
- case 'v':
- verbose_mode = true;
- break;
- case 'o':
- output = new std::ofstream;
- output->open(opt_arg);
- break;
- case 's': // --sourcedir
- tut::sSourceDir = opt_arg;
- // For convenience, so you can use tut::sSourceDir + "myfile"
- tut::sSourceDir += '/';
- break;
- case 't':
- touch = opt_arg;
- break;
- case 'w':
- wait_at_exit = true;
- break;
- case 'd':
- // *TODO: should come from error config file. We set it to
- // ERROR by default, so this allows full debug levels.
- LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
- break;
- default:
- stream_usage(std::cerr, argv[0]);
- return 1;
- break;
+ case 'g':
+ test_group.assign(opt_arg);
+ break;
+ case 'h':
+ stream_usage(std::cout, argv[0]);
+ return 0;
+ break;
+ case 'l':
+ stream_groups(std::cout, argv[0]);
+ return 0;
+ case 'v':
+ verbose_mode = true;
+ break;
+ case 'o':
+ output = new std::ofstream;
+ output->open(opt_arg);
+ break;
+ case 's': // --sourcedir
+ tut::sSourceDir = opt_arg;
+ // For convenience, so you can use tut::sSourceDir + "myfile"
+ tut::sSourceDir += '/';
+ break;
+ case 't':
+ touch = opt_arg;
+ break;
+ case 'w':
+ wait_at_exit = true;
+ break;
+ case 'd':
+ // *TODO: should come from error config file. We set it to
+ // ERROR by default, so this allows full debug levels.
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ break;
+ case 'x':
+ suite_name.assign(opt_arg);
+ break;
+ default:
+ stream_usage(std::cerr, argv[0]);
+ return 1;
+ break;
}
}
-
+
+ /*
+ // commented out test tunner logic which should be fixed when eliminate the duplicated LLTestCallback and LLTCTestCallaback classes
+ // become proper class:subclass
+ // if the Segmentation fault issue is resolved, all code in the block comments can be uncommented, and all code below can be removed.
+
+ LLTestCallback* mycallback;
+ if (getenv("TEAMCITY_PROJECT_NAME"))
+ {
+ mycallback = new LLTCTestCallback(verbose_mode, output, suite_name);
+
+ }
+ else
+ {
+ mycallback = new LLTestCallback(verbose_mode, output, suite_name);
+ }
+
+ tut::runner.get().set_callback(mycallback);
+
+ if(test_group.empty())
+ {
+ tut::runner.get().run_tests();
+ }
+ else
+ {
+ tut::runner.get().run_tests(test_group);
+ }
+
+ bool success = (mycallback->getFailedTests() == 0);
+
+ if (wait_at_exit)
+ {
+ std::cerr << "Press return to exit..." << std::endl;
+ std::cin.get();
+ }
+
+ if (output)
+ {
+ output->close();
+ delete output;
+ }
+
+ if (touch && success)
+ {
+ std::ofstream s;
+ s.open(touch);
+ s << "ok" << std::endl;
+ s.close();
+ }
+
+ apr_terminate();
+
+ int retval = (success ? 0 : 1);
+ return retval;
+ */
+
// run the tests
- LLTestCallback callback(verbose_mode, output);
- tut::runner.get().set_callback(&callback);
- if(test_group.empty())
+ if (getenv("TEAMCITY_PROJECT_NAME"))
{
- tut::runner.get().run_tests();
+ LLTCTestCallback* mycallback;
+ mycallback = new LLTCTestCallback(verbose_mode, output, suite_name);
+
+ tut::runner.get().set_callback(mycallback);
+
+ if(test_group.empty())
+ {
+ tut::runner.get().run_tests();
+ }
+ else
+ {
+ tut::runner.get().run_tests(test_group);
+ }
+
+ bool success = (mycallback->getFailedTests() == 0);
+
+ if (wait_at_exit)
+ {
+ std::cerr << "Press return to exit..." << std::endl;
+ std::cin.get();
+ }
+
+ if (output)
+ {
+ output->close();
+ delete output;
+ }
+
+ if (touch && success)
+ {
+ std::ofstream s;
+ s.open(touch);
+ s << "ok" << std::endl;
+ s.close();
+ }
+
+ apr_terminate();
+
+ int retval = (success ? 0 : 1);
+ return retval;
+
+
}
+ // NOT if (getenv("TEAMCITY_PROJECT_NAME"))
else
{
- tut::runner.get().run_tests(test_group);
- }
-
- bool success = (callback.getFailedTests() == 0);
-
- if (wait_at_exit)
- {
- std::cerr << "Press return to exit..." << std::endl;
- std::cin.get();
- }
-
- if (output)
- {
- output->close();
- delete output;
- }
-
- if (touch && success)
- {
- std::ofstream s;
- s.open(touch);
- s << "ok" << std::endl;
- s.close();
+ LLTestCallback* mycallback;
+ mycallback = new LLTestCallback(verbose_mode, output, suite_name);
+
+ tut::runner.get().set_callback(mycallback);
+
+ if(test_group.empty())
+ {
+ tut::runner.get().run_tests();
+ }
+ else
+ {
+ tut::runner.get().run_tests(test_group);
+ }
+
+ bool success = (mycallback->getFailedTests() == 0);
+
+ if (wait_at_exit)
+ {
+ std::cerr << "Press return to exit..." << std::endl;
+ std::cin.get();
+ }
+
+ if (output)
+ {
+ output->close();
+ delete output;
+ }
+
+ if (touch && success)
+ {
+ std::ofstream s;
+ s.open(touch);
+ s << "ok" << std::endl;
+ s.close();
+ }
+
+ apr_terminate();
+
+ int retval = (success ? 0 : 1);
+ return retval;
+
}
-
- apr_terminate();
-
- int retval = (success ? 0 : 1);
- return retval;
}