DRTVWR-476: Cherry-pick debug aids from commit 77b0c53 (fiber-mutex)
parent
b793ab8619
commit
dc07509f29
|
|
@ -191,9 +191,9 @@ namespace LLError
|
|||
The classes CallSite and Log are used by the logging macros below.
|
||||
They are not intended for general use.
|
||||
*/
|
||||
|
||||
|
||||
struct CallSite;
|
||||
|
||||
|
||||
class LL_COMMON_API Log
|
||||
{
|
||||
public:
|
||||
|
|
@ -202,8 +202,17 @@ namespace LLError
|
|||
static void flush(std::ostringstream* out, char* message);
|
||||
static void flush(std::ostringstream*, const CallSite&);
|
||||
static std::string demangle(const char* mangled);
|
||||
/// classname<TYPE>()
|
||||
template <typename T>
|
||||
static std::string classname() { return demangle(typeid(T).name()); }
|
||||
/// classname(some_pointer)
|
||||
template <typename T>
|
||||
static std::string classname(const T* ptr) { return demangle(typeid(*ptr).name()); }
|
||||
/// classname(some_reference)
|
||||
template <typename T>
|
||||
static std::string classname(const T& obj) { return demangle(typeid(obj).name()); }
|
||||
};
|
||||
|
||||
|
||||
struct LL_COMMON_API CallSite
|
||||
{
|
||||
// Represents a specific place in the code where a message is logged
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ protected:
|
|||
static void logdebugs(const char* p1, const char* p2="",
|
||||
const char* p3="", const char* p4="");
|
||||
static std::string demangle(const char* mangled);
|
||||
// these classname() declarations restate template functions declared in
|
||||
// llerror.h because we avoid #including that here
|
||||
template <typename T>
|
||||
static std::string classname() { return demangle(typeid(T).name()); }
|
||||
template <typename T>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "stringize.h"
|
||||
#include "tests/wrapllerrs.h"
|
||||
#include "../test/catch_and_store_what_in.h"
|
||||
#include "../test/debug.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
|
@ -45,15 +46,6 @@ using boost::lambda::var;
|
|||
|
||||
using namespace llsd;
|
||||
|
||||
/*****************************************************************************
|
||||
* Output control
|
||||
*****************************************************************************/
|
||||
#ifdef DEBUG_ON
|
||||
using std::cout;
|
||||
#else
|
||||
static std::ostringstream cout;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Example data, functions, classes
|
||||
*****************************************************************************/
|
||||
|
|
@ -155,13 +147,13 @@ struct Vars
|
|||
/*------------- no-args (non-const, const, static) methods -------------*/
|
||||
void method0()
|
||||
{
|
||||
cout << "method0()\n";
|
||||
debug()("method0()");
|
||||
i = 17;
|
||||
}
|
||||
|
||||
void cmethod0() const
|
||||
{
|
||||
cout << 'c';
|
||||
debug()('c', NONL);
|
||||
const_cast<Vars*>(this)->method0();
|
||||
}
|
||||
|
||||
|
|
@ -170,13 +162,13 @@ struct Vars
|
|||
/*------------ Callable (non-const, const, static) methods -------------*/
|
||||
void method1(const LLSD& obj)
|
||||
{
|
||||
cout << "method1(" << obj << ")\n";
|
||||
debug()("method1(", obj, ")");
|
||||
llsd = obj;
|
||||
}
|
||||
|
||||
void cmethod1(const LLSD& obj) const
|
||||
{
|
||||
cout << 'c';
|
||||
debug()('c', NONL);
|
||||
const_cast<Vars*>(this)->method1(obj);
|
||||
}
|
||||
|
||||
|
|
@ -196,12 +188,12 @@ struct Vars
|
|||
else
|
||||
vcp = std::string("'") + cp + "'";
|
||||
|
||||
cout << "methodna(" << b
|
||||
<< ", " << i
|
||||
<< ", " << f
|
||||
<< ", " << d
|
||||
<< ", " << vcp
|
||||
<< ")\n";
|
||||
debug()("methodna(", b,
|
||||
", ", i,
|
||||
", ", f,
|
||||
", ", d,
|
||||
", ", vcp,
|
||||
")");
|
||||
|
||||
this->b = b;
|
||||
this->i = i;
|
||||
|
|
@ -218,12 +210,12 @@ struct Vars
|
|||
vbin << std::hex << std::setfill('0') << std::setw(2) << unsigned(byte);
|
||||
}
|
||||
|
||||
cout << "methodnb(" << "'" << s << "'"
|
||||
<< ", " << uuid
|
||||
<< ", " << date
|
||||
<< ", '" << uri << "'"
|
||||
<< ", " << vbin.str()
|
||||
<< ")\n";
|
||||
debug()("methodnb(", "'", s, "'",
|
||||
", ", uuid,
|
||||
", ", date,
|
||||
", '", uri, "'",
|
||||
", ", vbin.str(),
|
||||
")");
|
||||
|
||||
this->s = s;
|
||||
this->uuid = uuid;
|
||||
|
|
@ -234,18 +226,30 @@ struct Vars
|
|||
|
||||
void cmethodna(NPARAMSa) const
|
||||
{
|
||||
cout << 'c';
|
||||
debug()('c', NONL);
|
||||
const_cast<Vars*>(this)->methodna(NARGSa);
|
||||
}
|
||||
|
||||
void cmethodnb(NPARAMSb) const
|
||||
{
|
||||
cout << 'c';
|
||||
debug()('c', NONL);
|
||||
const_cast<Vars*>(this)->methodnb(NARGSb);
|
||||
}
|
||||
|
||||
static void smethodna(NPARAMSa);
|
||||
static void smethodnb(NPARAMSb);
|
||||
|
||||
static Debug& debug()
|
||||
{
|
||||
// Lazily initialize this Debug instance so it can notice if main()
|
||||
// has forcibly set LOGTEST. If it were simply a static member, it
|
||||
// would already have examined the environment variable by the time
|
||||
// main() gets around to checking command-line switches. Since we have
|
||||
// a global static Vars instance, the same would be true of a plain
|
||||
// non-static member.
|
||||
static Debug sDebug("Vars");
|
||||
return sDebug;
|
||||
}
|
||||
};
|
||||
/*------- Global Vars instance for free functions and static methods -------*/
|
||||
static Vars g;
|
||||
|
|
@ -253,25 +257,25 @@ static Vars g;
|
|||
/*------------ Static Vars method implementations reference 'g' ------------*/
|
||||
void Vars::smethod0()
|
||||
{
|
||||
cout << "smethod0() -> ";
|
||||
debug()("smethod0() -> ", NONL);
|
||||
g.method0();
|
||||
}
|
||||
|
||||
void Vars::smethod1(const LLSD& obj)
|
||||
{
|
||||
cout << "smethod1(" << obj << ") -> ";
|
||||
debug()("smethod1(", obj, ") -> ", NONL);
|
||||
g.method1(obj);
|
||||
}
|
||||
|
||||
void Vars::smethodna(NPARAMSa)
|
||||
{
|
||||
cout << "smethodna(...) -> ";
|
||||
debug()("smethodna(...) -> ", NONL);
|
||||
g.methodna(NARGSa);
|
||||
}
|
||||
|
||||
void Vars::smethodnb(NPARAMSb)
|
||||
{
|
||||
cout << "smethodnb(...) -> ";
|
||||
debug()("smethodnb(...) -> ", NONL);
|
||||
g.methodnb(NARGSb);
|
||||
}
|
||||
|
||||
|
|
@ -284,25 +288,25 @@ void clear()
|
|||
/*------------------- Free functions also reference 'g' --------------------*/
|
||||
void free0()
|
||||
{
|
||||
cout << "free0() -> ";
|
||||
g.debug()("free0() -> ", NONL);
|
||||
g.method0();
|
||||
}
|
||||
|
||||
void free1(const LLSD& obj)
|
||||
{
|
||||
cout << "free1(" << obj << ") -> ";
|
||||
g.debug()("free1(", obj, ") -> ", NONL);
|
||||
g.method1(obj);
|
||||
}
|
||||
|
||||
void freena(NPARAMSa)
|
||||
{
|
||||
cout << "freena(...) -> ";
|
||||
g.debug()("freena(...) -> ", NONL);
|
||||
g.methodna(NARGSa);
|
||||
}
|
||||
|
||||
void freenb(NPARAMSb)
|
||||
{
|
||||
cout << "freenb(...) -> ";
|
||||
g.debug()("freenb(...) -> ", NONL);
|
||||
g.methodnb(NARGSb);
|
||||
}
|
||||
|
||||
|
|
@ -313,6 +317,7 @@ namespace tut
|
|||
{
|
||||
struct lleventdispatcher_data
|
||||
{
|
||||
Debug debug{"test"};
|
||||
WrapLLErrs redirect;
|
||||
Dispatcher work;
|
||||
Vars v;
|
||||
|
|
@ -431,7 +436,12 @@ namespace tut
|
|||
// Same for freenb() et al.
|
||||
params = LLSDMap("a", LLSDArray("b")("i")("f")("d")("cp"))
|
||||
("b", LLSDArray("s")("uuid")("date")("uri")("bin"));
|
||||
cout << "params:\n" << params << "\nparams[\"a\"]:\n" << params["a"] << "\nparams[\"b\"]:\n" << params["b"] << std::endl;
|
||||
debug("params:\n",
|
||||
params, "\n"
|
||||
"params[\"a\"]:\n",
|
||||
params["a"], "\n"
|
||||
"params[\"b\"]:\n",
|
||||
params["b"]);
|
||||
// default LLSD::Binary value
|
||||
std::vector<U8> binary;
|
||||
for (size_t ix = 0, h = 0xaa; ix < 6; ++ix, h += 0x11)
|
||||
|
|
@ -448,7 +458,8 @@ namespace tut
|
|||
(LLDate::now())
|
||||
(LLURI("http://www.ietf.org/rfc/rfc3986.txt"))
|
||||
(binary));
|
||||
cout << "dft_array_full:\n" << dft_array_full << std::endl;
|
||||
debug("dft_array_full:\n",
|
||||
dft_array_full);
|
||||
// Partial defaults arrays.
|
||||
foreach(LLSD::String a, ab)
|
||||
{
|
||||
|
|
@ -457,7 +468,8 @@ namespace tut
|
|||
llsd_copy_array(dft_array_full[a].beginArray() + partition,
|
||||
dft_array_full[a].endArray());
|
||||
}
|
||||
cout << "dft_array_partial:\n" << dft_array_partial << std::endl;
|
||||
debug("dft_array_partial:\n",
|
||||
dft_array_partial);
|
||||
|
||||
foreach(LLSD::String a, ab)
|
||||
{
|
||||
|
|
@ -473,7 +485,10 @@ namespace tut
|
|||
dft_map_partial[a][params[a][ix].asString()] = dft_array_full[a][ix];
|
||||
}
|
||||
}
|
||||
cout << "dft_map_full:\n" << dft_map_full << "\ndft_map_partial:\n" << dft_map_partial << '\n';
|
||||
debug("dft_map_full:\n",
|
||||
dft_map_full, "\n"
|
||||
"dft_map_partial:\n",
|
||||
dft_map_partial);
|
||||
|
||||
// (Free function | static method) with (no | arbitrary) params,
|
||||
// map style, no (empty array) defaults
|
||||
|
|
@ -918,7 +933,12 @@ namespace tut
|
|||
params[a].endArray()),
|
||||
dft_array_partial[a]);
|
||||
}
|
||||
cout << "allreq:\n" << allreq << "\nleftreq:\n" << leftreq << "\nrightdft:\n" << rightdft << std::endl;
|
||||
debug("allreq:\n",
|
||||
allreq, "\n"
|
||||
"leftreq:\n",
|
||||
leftreq, "\n"
|
||||
"rightdft:\n",
|
||||
rightdft);
|
||||
|
||||
// Generate maps containing parameter names not provided by the
|
||||
// dft_map_partial maps.
|
||||
|
|
@ -930,7 +950,8 @@ namespace tut
|
|||
skipreq[a].erase(me.first);
|
||||
}
|
||||
}
|
||||
cout << "skipreq:\n" << skipreq << std::endl;
|
||||
debug("skipreq:\n",
|
||||
skipreq);
|
||||
|
||||
LLSD groups(LLSDArray // array of groups
|
||||
|
||||
|
|
@ -975,7 +996,11 @@ namespace tut
|
|||
LLSD names(grp[0]);
|
||||
LLSD required(grp[1][0]);
|
||||
LLSD optional(grp[1][1]);
|
||||
cout << "For " << names << ",\n" << "required:\n" << required << "\noptional:\n" << optional << std::endl;
|
||||
debug("For ", names, ",\n",
|
||||
"required:\n",
|
||||
required, "\n"
|
||||
"optional:\n",
|
||||
optional);
|
||||
|
||||
// Loop through 'names'
|
||||
foreach(LLSD nm, inArray(names))
|
||||
|
|
@ -1163,7 +1188,7 @@ namespace tut
|
|||
}
|
||||
// Adjust expect["a"]["cp"] for special Vars::cp treatment.
|
||||
expect["a"]["cp"] = std::string("'") + expect["a"]["cp"].asString() + "'";
|
||||
cout << "expect: " << expect << '\n';
|
||||
debug("expect: ", expect);
|
||||
|
||||
// Use substantially the same logic for args and argsplus
|
||||
LLSD argsarrays(LLSDArray(args)(argsplus));
|
||||
|
|
@ -1218,7 +1243,8 @@ namespace tut
|
|||
{
|
||||
array_overfull[a].append("bogus");
|
||||
}
|
||||
cout << "array_full: " << array_full << "\narray_overfull: " << array_overfull << std::endl;
|
||||
debug("array_full: ", array_full, "\n"
|
||||
"array_overfull: ", array_overfull);
|
||||
// We rather hope that LLDate::now() will generate a timestamp
|
||||
// distinct from the one it generated in the constructor, moments ago.
|
||||
ensure_not_equals("Timestamps too close",
|
||||
|
|
@ -1233,7 +1259,8 @@ namespace tut
|
|||
map_overfull[a] = map_full[a];
|
||||
map_overfull[a]["extra"] = "ignore";
|
||||
}
|
||||
cout << "map_full: " << map_full << "\nmap_overfull: " << map_overfull << std::endl;
|
||||
debug("map_full: ", map_full, "\n"
|
||||
"map_overfull: ", map_overfull);
|
||||
LLSD expect(map_full);
|
||||
// Twiddle the const char* param.
|
||||
expect["a"]["cp"] = std::string("'") + expect["a"]["cp"].asString() + "'";
|
||||
|
|
@ -1248,7 +1275,7 @@ namespace tut
|
|||
// so won't bother returning it. Predict that behavior to match the
|
||||
// LLSD values.
|
||||
expect["a"].erase("b");
|
||||
cout << "expect: " << expect << std::endl;
|
||||
debug("expect: ", expect);
|
||||
// For this test, calling functions registered with different sets of
|
||||
// parameter defaults should make NO DIFFERENCE WHATSOEVER. Every call
|
||||
// should pass all params.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* @file chained_callback.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2020-01-03
|
||||
* @brief Subclass of tut::callback used for chaining callbacks.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
|
||||
* Copyright (c) 2020, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_CHAINED_CALLBACK_H)
|
||||
#define LL_CHAINED_CALLBACK_H
|
||||
|
||||
/**
|
||||
* Derive your TUT callback from chained_callback instead of tut::callback to
|
||||
* ensure that multiple such callbacks can coexist in a given test executable.
|
||||
* The relevant callback method will be called for each callback instance in
|
||||
* reverse order of the instance's link() methods being called: the most
|
||||
* recently link()ed callback will be called first, then the previous, and so
|
||||
* forth.
|
||||
*
|
||||
* Obviously, for this to work, all relevant callbacks must be derived from
|
||||
* chained_callback instead of tut::callback. Given that, control should reach
|
||||
* each of them regardless of their construction order. The chain is
|
||||
* guaranteed to stop because the first link() call will link to test_runner's
|
||||
* default_callback, which is simply an instance of the callback() base class.
|
||||
*
|
||||
* The rule for deriving from chained_callback is that you may override any of
|
||||
* its virtual methods, but your override must at some point call the
|
||||
* corresponding chained_callback method.
|
||||
*/
|
||||
class chained_callback: public tut::callback
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Instead of calling tut::test_runner::set_callback(&your_callback), call
|
||||
* your_callback.link();
|
||||
* This uses the canonical instance of tut::test_runner.
|
||||
*/
|
||||
void link()
|
||||
{
|
||||
link(tut::runner.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* If for some reason you have a different instance of test_runner...
|
||||
*/
|
||||
void link(tut::test_runner& runner)
|
||||
{
|
||||
// Since test_runner's constructor sets a default callback,
|
||||
// get_callback() will always return a reference to a valid callback
|
||||
// instance.
|
||||
mPrev = &runner.get_callback();
|
||||
runner.set_callback(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when new test run started.
|
||||
*/
|
||||
virtual void run_started()
|
||||
{
|
||||
mPrev->run_started();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a group started
|
||||
* @param name Name of the group
|
||||
*/
|
||||
virtual void group_started(const std::string& name)
|
||||
{
|
||||
mPrev->group_started(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a test finished.
|
||||
* @param tr Test results.
|
||||
*/
|
||||
virtual void test_completed(const tut::test_result& tr)
|
||||
{
|
||||
mPrev->test_completed(tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a group is completed
|
||||
* @param name Name of the group
|
||||
*/
|
||||
virtual void group_completed(const std::string& name)
|
||||
{
|
||||
mPrev->group_completed(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when all tests in run completed.
|
||||
*/
|
||||
virtual void run_completed()
|
||||
{
|
||||
mPrev->run_completed();
|
||||
}
|
||||
|
||||
private:
|
||||
tut::callback* mPrev;
|
||||
};
|
||||
|
||||
#endif /* ! defined(LL_CHAINED_CALLBACK_H) */
|
||||
|
|
@ -29,37 +29,59 @@
|
|||
#if ! defined(LL_DEBUG_H)
|
||||
#define LL_DEBUG_H
|
||||
|
||||
#include <iostream>
|
||||
#include "print.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Debugging stuff
|
||||
*****************************************************************************/
|
||||
// This class is intended to illuminate entry to a given block, exit from the
|
||||
// same block and checkpoints along the way. It also provides a convenient
|
||||
// place to turn std::cout output on and off.
|
||||
/**
|
||||
* This class is intended to illuminate entry to a given block, exit from the
|
||||
* same block and checkpoints along the way. It also provides a convenient
|
||||
* place to turn std::cerr output on and off.
|
||||
*
|
||||
* If the environment variable LOGTEST is non-empty, each Debug instance will
|
||||
* announce its construction and destruction, presumably at entry and exit to
|
||||
* the block in which it's declared. Moreover, any arguments passed to its
|
||||
* operator()() will be streamed to std::cerr, prefixed by the block
|
||||
* description.
|
||||
*
|
||||
* The variable LOGTEST is used because that's the environment variable
|
||||
* checked by test.cpp, our TUT main() program, to turn on LLError logging. It
|
||||
* is expected that Debug is solely for use in test programs.
|
||||
*/
|
||||
class Debug
|
||||
{
|
||||
public:
|
||||
Debug(const std::string& block):
|
||||
mBlock(block)
|
||||
mBlock(block),
|
||||
mLOGTEST(getenv("LOGTEST")),
|
||||
// debug output enabled when LOGTEST is set AND non-empty
|
||||
mEnabled(mLOGTEST && *mLOGTEST)
|
||||
{
|
||||
(*this)("entry");
|
||||
}
|
||||
|
||||
// non-copyable
|
||||
Debug(const Debug&) = delete;
|
||||
|
||||
~Debug()
|
||||
{
|
||||
(*this)("exit");
|
||||
}
|
||||
|
||||
void operator()(const std::string& status)
|
||||
template <typename... ARGS>
|
||||
void operator()(ARGS&&... args)
|
||||
{
|
||||
#if defined(DEBUG_ON)
|
||||
std::cout << mBlock << ' ' << status << std::endl;
|
||||
#endif
|
||||
if (mEnabled)
|
||||
{
|
||||
print(mBlock, ' ', std::forward<ARGS>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string mBlock;
|
||||
const char* mLOGTEST;
|
||||
bool mEnabled;
|
||||
};
|
||||
|
||||
// It's often convenient to use the name of the enclosing function as the name
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* @file print.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2020-01-02
|
||||
* @brief print() function for debugging
|
||||
*
|
||||
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
|
||||
* Copyright (c) 2020, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_PRINT_H)
|
||||
#define LL_PRINT_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// print(..., NONL);
|
||||
// leaves the output dangling, suppressing the normally appended std::endl
|
||||
struct NONL_t {};
|
||||
#define NONL (NONL_t())
|
||||
|
||||
// normal recursion end
|
||||
inline
|
||||
void print()
|
||||
{
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
// print(NONL) is a no-op
|
||||
inline
|
||||
void print(NONL_t)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T, typename... ARGS>
|
||||
void print(T&& first, ARGS&&... rest)
|
||||
{
|
||||
std::cerr << first;
|
||||
print(std::forward<ARGS>(rest)...);
|
||||
}
|
||||
|
||||
#endif /* ! defined(LL_PRINT_H) */
|
||||
|
|
@ -37,6 +37,7 @@
|
|||
#include "linden_common.h"
|
||||
#include "llerrorcontrol.h"
|
||||
#include "lltut.h"
|
||||
#include "chained_callback.h"
|
||||
#include "stringize.h"
|
||||
#include "namedtempfile.h"
|
||||
#include "lltrace.h"
|
||||
|
|
@ -71,7 +72,6 @@
|
|||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/lambda/lambda.hpp>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
|
|
@ -172,8 +172,10 @@ private:
|
|||
LLError::RecorderPtr mRecorder;
|
||||
};
|
||||
|
||||
class LLTestCallback : public tut::callback
|
||||
class LLTestCallback : public chained_callback
|
||||
{
|
||||
typedef chained_callback super;
|
||||
|
||||
public:
|
||||
LLTestCallback(bool verbose_mode, std::ostream *stream,
|
||||
boost::shared_ptr<LLReplayLog> replayer) :
|
||||
|
|
@ -184,7 +186,7 @@ public:
|
|||
mSkippedTests(0),
|
||||
// By default, capture a shared_ptr to std::cout, with a no-op "deleter"
|
||||
// so that destroying the shared_ptr makes no attempt to delete std::cout.
|
||||
mStream(boost::shared_ptr<std::ostream>(&std::cout, boost::lambda::_1)),
|
||||
mStream(boost::shared_ptr<std::ostream>(&std::cout, [](std::ostream*){})),
|
||||
mReplayer(replayer)
|
||||
{
|
||||
if (stream)
|
||||
|
|
@ -205,22 +207,25 @@ public:
|
|||
|
||||
~LLTestCallback()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
virtual void run_started()
|
||||
{
|
||||
//std::cout << "run_started" << std::endl;
|
||||
LL_INFOS("TestRunner")<<"Test Started"<< LL_ENDL;
|
||||
super::run_started();
|
||||
}
|
||||
|
||||
virtual void group_started(const std::string& name) {
|
||||
LL_INFOS("TestRunner")<<"Unit test group_started name=" << name << LL_ENDL;
|
||||
*mStream << "Unit test group_started name=" << name << std::endl;
|
||||
super::group_started(name);
|
||||
}
|
||||
|
||||
virtual void group_completed(const std::string& name) {
|
||||
LL_INFOS("TestRunner")<<"Unit test group_completed name=" << name << LL_ENDL;
|
||||
*mStream << "Unit test group_completed name=" << name << std::endl;
|
||||
super::group_completed(name);
|
||||
}
|
||||
|
||||
virtual void test_completed(const tut::test_result& tr)
|
||||
|
|
@ -282,6 +287,7 @@ public:
|
|||
*mStream << std::endl;
|
||||
}
|
||||
LL_INFOS("TestRunner")<<out.str()<<LL_ENDL;
|
||||
super::test_completed(tr);
|
||||
}
|
||||
|
||||
virtual int getFailedTests() const { return mFailedTests; }
|
||||
|
|
@ -309,6 +315,7 @@ public:
|
|||
*mStream << "Please report or fix the problem." << std::endl;
|
||||
*mStream << "*********************************" << std::endl;
|
||||
}
|
||||
super::run_completed();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -474,9 +481,8 @@ void stream_usage(std::ostream& s, const char* app)
|
|||
<< "LOGTEST=level : for all tests, emit log messages at level 'level'\n"
|
||||
<< "LOGFAIL=level : only for failed tests, emit log messages at level 'level'\n"
|
||||
<< "where 'level' is one of ALL, DEBUG, INFO, WARN, ERROR, NONE.\n"
|
||||
<< "--debug is like LOGTEST=DEBUG, but --debug overrides LOGTEST.\n"
|
||||
<< "Setting LOGFAIL overrides both LOGTEST and --debug: the only log\n"
|
||||
<< "messages you will see will be for failed tests.\n\n";
|
||||
<< "--debug is like LOGTEST=DEBUG, but --debug overrides LOGTEST,\n"
|
||||
<< "while LOGTEST overrides LOGFAIL.\n\n";
|
||||
|
||||
s << "Examples:" << std::endl;
|
||||
s << " " << app << " --verbose" << std::endl;
|
||||
|
|
@ -520,35 +526,8 @@ int main(int argc, char **argv)
|
|||
#ifndef LL_WINDOWS
|
||||
::testing::InitGoogleMock(&argc, argv);
|
||||
#endif
|
||||
// LOGTEST overrides default, but can be overridden by --debug or LOGFAIL.
|
||||
const char* LOGTEST = getenv("LOGTEST");
|
||||
if (LOGTEST)
|
||||
{
|
||||
LLError::initForApplication(".", ".", true /* log to stderr */);
|
||||
LLError::setDefaultLevel(LLError::decodeLevel(LOGTEST));
|
||||
}
|
||||
else
|
||||
{
|
||||
LLError::initForApplication(".", ".", false /* do not log to stderr */);
|
||||
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
|
||||
}
|
||||
LLError::setFatalFunction(wouldHaveCrashed);
|
||||
std::string test_app_name(argv[0]);
|
||||
std::string test_log = test_app_name + ".log";
|
||||
LLFile::remove(test_log);
|
||||
LLError::logToFile(test_log);
|
||||
|
||||
#ifdef CTYPE_WORKAROUND
|
||||
ctype_workaround();
|
||||
#endif
|
||||
|
||||
ll_init_apr();
|
||||
|
||||
if (!sMasterThreadRecorder)
|
||||
{
|
||||
sMasterThreadRecorder = new LLTrace::ThreadRecorder();
|
||||
LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
|
||||
}
|
||||
apr_getopt_t* os = NULL;
|
||||
if(APR_SUCCESS != apr_getopt_init(&os, gAPRPoolp, argc, argv))
|
||||
{
|
||||
|
|
@ -562,7 +541,13 @@ int main(int argc, char **argv)
|
|||
std::string test_group;
|
||||
std::string suite_name;
|
||||
|
||||
// values use for options parsing
|
||||
// LOGTEST overrides default, but can be overridden by --debug.
|
||||
const char* LOGTEST = getenv("LOGTEST");
|
||||
|
||||
// DELETE
|
||||
LOGTEST = "DEBUG";
|
||||
|
||||
// values used for options parsing
|
||||
apr_status_t apr_err;
|
||||
const char* opt_arg = NULL;
|
||||
int opt_id = 0;
|
||||
|
|
@ -611,10 +596,7 @@ int main(int argc, char **argv)
|
|||
wait_at_exit = true;
|
||||
break;
|
||||
case 'd':
|
||||
// this is what LLError::initForApplication() does internally
|
||||
// when you pass log_to_stderr=true
|
||||
LLError::logToStderr();
|
||||
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
|
||||
LOGTEST = "DEBUG";
|
||||
break;
|
||||
case 'x':
|
||||
suite_name.assign(opt_arg);
|
||||
|
|
@ -626,22 +608,44 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
// run the tests
|
||||
|
||||
// set up logging
|
||||
const char* LOGFAIL = getenv("LOGFAIL");
|
||||
boost::shared_ptr<LLReplayLog> replayer;
|
||||
// As described in stream_usage(), LOGFAIL overrides both --debug and
|
||||
// LOGTEST. But allow user to set LOGFAIL empty to revert to LOGTEST
|
||||
// and/or --debug.
|
||||
if (LOGFAIL && *LOGFAIL)
|
||||
boost::shared_ptr<LLReplayLog> replayer{boost::make_shared<LLReplayLog>()};
|
||||
|
||||
// Testing environment variables for both 'set' and 'not empty' allows a
|
||||
// user to suppress a pre-existing environment variable by forcing empty.
|
||||
if (LOGTEST && *LOGTEST)
|
||||
{
|
||||
LLError::ELevel level = LLError::decodeLevel(LOGFAIL);
|
||||
replayer.reset(new LLReplayLogReal(level, gAPRPoolp));
|
||||
LLError::initForApplication(".", ".", true /* log to stderr */);
|
||||
LLError::setDefaultLevel(LLError::decodeLevel(LOGTEST));
|
||||
}
|
||||
else
|
||||
{
|
||||
replayer.reset(new LLReplayLog());
|
||||
LLError::initForApplication(".", ".", false /* do not log to stderr */);
|
||||
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
|
||||
if (LOGFAIL && *LOGFAIL)
|
||||
{
|
||||
LLError::ELevel level = LLError::decodeLevel(LOGFAIL);
|
||||
replayer.reset(new LLReplayLogReal(level, gAPRPoolp));
|
||||
}
|
||||
}
|
||||
LLError::setFatalFunction(wouldHaveCrashed);
|
||||
std::string test_app_name(argv[0]);
|
||||
std::string test_log = test_app_name + ".log";
|
||||
LLFile::remove(test_log);
|
||||
LLError::logToFile(test_log);
|
||||
|
||||
#ifdef CTYPE_WORKAROUND
|
||||
ctype_workaround();
|
||||
#endif
|
||||
|
||||
if (!sMasterThreadRecorder)
|
||||
{
|
||||
sMasterThreadRecorder = new LLTrace::ThreadRecorder();
|
||||
LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
|
||||
}
|
||||
|
||||
// run the tests
|
||||
|
||||
LLTestCallback* mycallback;
|
||||
if (getenv("TEAMCITY_PROJECT_NAME"))
|
||||
|
|
@ -653,7 +657,8 @@ int main(int argc, char **argv)
|
|||
mycallback = new LLTestCallback(verbose_mode, output.get(), replayer);
|
||||
}
|
||||
|
||||
tut::runner.get().set_callback(mycallback);
|
||||
// a chained_callback subclass must be linked with previous
|
||||
mycallback->link();
|
||||
|
||||
if(test_group.empty())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
#include "llsd.h"
|
||||
#include "../../../test/lltut.h"
|
||||
#include "../../../test/lltestapp.h"
|
||||
//#define DEBUG_ON
|
||||
#include "../../../test/debug.h"
|
||||
#include "llevents.h"
|
||||
#include "lleventcoro.h"
|
||||
|
|
|
|||
Loading…
Reference in New Issue