diff options
| -rw-r--r-- | indra/llcommon/llerror.h | 15 | ||||
| -rw-r--r-- | indra/llcommon/llsingleton.h | 2 | ||||
| -rw-r--r-- | indra/llcommon/tests/lleventdispatcher_test.cpp | 119 | ||||
| -rw-r--r-- | indra/test/chained_callback.h | 105 | ||||
| -rw-r--r-- | indra/test/debug.h | 40 | ||||
| -rw-r--r-- | indra/test/print.h | 42 | ||||
| -rw-r--r-- | indra/test/test.cpp | 105 | ||||
| -rw-r--r-- | indra/viewer_components/login/tests/lllogin_test.cpp | 1 | 
8 files changed, 320 insertions, 109 deletions
| diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 48162eca9e..3cdd051ac7 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -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 diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 27c2ceb3b6..ccd2e48bf2 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -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> diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp index efb75951be..9da1ecfd67 100644 --- a/indra/llcommon/tests/lleventdispatcher_test.cpp +++ b/indra/llcommon/tests/lleventdispatcher_test.cpp @@ -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> @@ -46,15 +47,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  *****************************************************************************/  // We don't need a whole lot of different arbitrary-params methods, just (no | @@ -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. diff --git a/indra/test/chained_callback.h b/indra/test/chained_callback.h new file mode 100644 index 0000000000..41a7f7c9fa --- /dev/null +++ b/indra/test/chained_callback.h @@ -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) */ diff --git a/indra/test/debug.h b/indra/test/debug.h index 33c3ea2d27..76dbb973b2 100644 --- a/indra/test/debug.h +++ b/indra/test/debug.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 diff --git a/indra/test/print.h b/indra/test/print.h new file mode 100644 index 0000000000..08e36caddf --- /dev/null +++ b/indra/test/print.h @@ -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) */ diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 6b342ffe89..ea54ba658e 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -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())  	{ diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp index 0255e10e53..0d933a3d64 100644 --- a/indra/viewer_components/login/tests/lllogin_test.cpp +++ b/indra/viewer_components/login/tests/lllogin_test.cpp @@ -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" | 
