summaryrefslogtreecommitdiff
path: root/indra/test/test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/test/test.cpp')
-rw-r--r--indra/test/test.cpp338
1 files changed, 224 insertions, 114 deletions
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 7dfe8f40b7..ffdb0cb976 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -4,31 +4,25 @@
* @date 2005-09-26
* @brief Entry point for the test app.
*
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- *
- * Copyright (c) 2005-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -62,7 +56,7 @@
namespace tut
{
std::string sSourceDir;
-
+
test_runner_singleton runner;
}
@@ -70,54 +64,66 @@ 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)
+ mVerboseMode(verbose_mode),
+ mTotalTests(0),
+ mPassedTests(0),
+ mFailedTests(0),
+ mSkippedTests(0),
+ mStream(stream)
{
}
- 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 << "Unit test group_started name=" << name << std::endl;
+ }
+
+ virtual void group_completed(const std::string& name) {
+ std::cout << "Unit test 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))
{
@@ -134,7 +140,7 @@ public:
}
}
- void run_completed()
+ virtual void run_completed()
{
if (mStream)
{
@@ -143,10 +149,9 @@ public:
run_completed_(std::cout);
}
- int getFailedTests() const { return mFailedTests; }
-
-private:
- void run_completed_(std::ostream &stream)
+ virtual int getFailedTests() const { return mFailedTests; }
+
+ virtual void run_completed_(std::ostream &stream)
{
stream << "\tTotal Tests:\t" << mTotalTests << std::endl;
stream << "\tPassed Tests:\t" << mPassedTests;
@@ -159,7 +164,7 @@ private:
if (mSkippedTests > 0)
{
stream << "\tSkipped known failures:\t" << mSkippedTests
- << std::endl;
+ << std::endl;
}
if(mFailedTests > 0)
@@ -180,6 +185,94 @@ protected:
std::ostream *mStream;
};
+// 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) :
+ LLTestCallback(verbose_mode, stream),
+ mTCStream()
+ {
+ }
+
+ ~LLTCTestCallback()
+ {
+ }
+
+ virtual void group_started(const std::string& name) {
+ LLTestCallback::group_started(name);
+ mTCStream << "\n##teamcity[testSuiteStarted name='" << name << "']" << std::endl;
+ }
+
+ virtual void group_completed(const std::string& name) {
+ LLTestCallback::group_completed(name);
+ mTCStream << "##teamcity[testSuiteFinished name='" << name << "']" << std::endl;
+ }
+
+ virtual void test_completed(const tut::test_result& tr)
+ {
+ LLTestCallback::test_completed(tr);
+
+ switch(tr.result)
+ {
+ case tut::test_result::ok:
+ mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
+ mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
+ break;
+ case tut::test_result::fail:
+ mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
+ mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
+ mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
+ break;
+ case tut::test_result::ex:
+ mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
+ mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
+ mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
+ break;
+ case tut::test_result::warn:
+ mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
+ mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
+ mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
+ break;
+ case tut::test_result::term:
+ mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
+ mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
+ mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
+ break;
+ case tut::test_result::skip:
+ mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
+ mTCStream << "##teamcity[testIgnored name='" << tr.group << "." << tr.test << "']" << std::endl;
+ mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ virtual void run_completed()
+ {
+ LLTestCallback::run_completed();
+
+ // dump the TC reporting results to cout
+ tc_run_completed_(std::cout);
+ }
+
+ virtual void tc_run_completed_(std::ostream &stream)
+ {
+
+ // dump the TC reporting results to cout
+ stream << mTCStream.str() << std::endl;
+ }
+
+protected:
+ std::ostringstream mTCStream;
+
+};
+
+
static const apr_getopt_option_t TEST_CL_OPTIONS[] =
{
{"help", 'h', 0, "Print the help message."},
@@ -191,13 +284,14 @@ 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;
@@ -207,7 +301,7 @@ void stream_usage(std::ostream& s, const char* app)
{
s << " ";
s << " -" << (char)option->optch << ", --" << option->name
- << std::endl;
+ << std::endl;
s << "\t" << option->description << std::endl << std::endl;
++option;
}
@@ -248,9 +342,9 @@ 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
@@ -273,6 +367,7 @@ int main(int argc, char **argv)
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;
@@ -280,7 +375,7 @@ int main(int argc, char **argv)
int opt_id = 0;
std::ofstream *output = NULL;
const char *touch = NULL;
-
+
while(true)
{
apr_err = apr_getopt_long(os, TEST_CL_OPTIONS, &opt_id, &opt_arg);
@@ -289,55 +384,68 @@ 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;
}
}
// run the tests
- LLTestCallback callback(verbose_mode, output);
- tut::runner.get().set_callback(&callback);
-
+
+ LLTestCallback* mycallback;
+ if (getenv("TEAMCITY_PROJECT_NAME"))
+ {
+ mycallback = new LLTCTestCallback(verbose_mode, output);
+ }
+ else
+ {
+ mycallback = new LLTestCallback(verbose_mode, output);
+ }
+
+ tut::runner.get().set_callback(mycallback);
+
if(test_group.empty())
{
tut::runner.get().run_tests();
@@ -347,14 +455,14 @@ int main(int argc, char **argv)
tut::runner.get().run_tests(test_group);
}
- bool success = (callback.getFailedTests() == 0);
+ bool success = (mycallback->getFailedTests() == 0);
if (wait_at_exit)
{
std::cerr << "Press return to exit..." << std::endl;
std::cin.get();
}
-
+
if (output)
{
output->close();
@@ -368,9 +476,11 @@ int main(int argc, char **argv)
s << "ok" << std::endl;
s.close();
}
-
+
apr_terminate();
-
+
int retval = (success ? 0 : 1);
return retval;
+
+ //delete mycallback;
}