diff options
| author | brad kittenbrink <brad@lindenlab.com> | 2009-07-30 19:39:08 -0700 | 
|---|---|---|
| committer | brad kittenbrink <brad@lindenlab.com> | 2009-07-30 19:39:08 -0700 | 
| commit | a7efd0d8ddb68315653265d7e4ab87a156e56560 (patch) | |
| tree | 4210ae49796fdb8fb4b28f0bdd857dc338110070 /indra/test | |
| parent | b3a83059c464c9a974d547f57ab8e93ca0bee0f1 (diff) | |
| parent | 29607ab70edea79cfdceaa52d632d77e6699cb8f (diff) | |
Merged in viewer-2.0.0-3 changes up through r129050.  Boost got clobbered so I'll need to rebuild that, plus a couple other minor clenaups.
Diffstat (limited to 'indra/test')
| -rw-r--r-- | indra/test/CMakeLists.txt | 24 | ||||
| -rw-r--r-- | indra/test/debug.h | 68 | ||||
| -rw-r--r-- | indra/test/llevents_tut.cpp | 133 | ||||
| -rwxr-xr-x | indra/test/llsdmessagebuilder_tut.cpp | 2 | ||||
| -rwxr-xr-x | indra/test/llsdmessagereader_tut.cpp | 1 | ||||
| -rw-r--r-- | indra/test/llsdutil_tut.cpp | 235 | ||||
| -rw-r--r-- | indra/test/lltut.cpp | 12 | ||||
| -rw-r--r-- | indra/test/lltut.h | 3 | ||||
| -rw-r--r-- | indra/test/test.cpp | 19 | 
9 files changed, 361 insertions, 136 deletions
| diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index 463eedb4fd..012c5e6408 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -13,7 +13,7 @@ include(LLXML)  include(LScript)  include(Linking)  include(Tut) -include(Boost) +  include_directories(      ${LLCOMMON_INCLUDE_DIRS} @@ -93,6 +93,7 @@ set(test_SOURCE_FILES  set(test_HEADER_FILES      CMakeLists.txt +    debug.h      llpipeutil.h      llsdtraits.h      lltut.h @@ -126,6 +127,7 @@ target_link_libraries(test      ${LLXML_LIBRARIES}      ${LSCRIPT_LIBRARIES}      ${LLCOMMON_LIBRARIES} +	${EXPAT_LIBRARIES}      ${APRICONV_LIBRARIES}      ${PTHREAD_LIBRARY}      ${WINDOWS_LIBRARIES} @@ -145,16 +147,26 @@ endif (WINDOWS)  get_target_property(TEST_EXE test LOCATION) -add_custom_command( +IF(WINDOWS) +  set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}) +ELSE(WINDOWS) +  set(LD_LIBRARY_PATH ${ARCH_PREBUILT_DIRS}:/usr/lib) +ENDIF(WINDOWS) + +SET(TEST_CMD ${TEST_EXE} --output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt --touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt) + +ADD_CUSTOM_COMMAND(    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt -  COMMAND ${TEST_EXE} +  COMMAND ${CMAKE_COMMAND}    ARGS -    --output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt -    --touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt +    -DLD_LIBRARY_PATH=${LD_LIBRARY_PATH} +    "-DTEST_CMD:STRING=\"${TEST_CMD}\""  +    -P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake +          DEPENDS test    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}    COMMENT "C++ unit tests" -  ) + )  set(test_results ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt) diff --git a/indra/test/debug.h b/indra/test/debug.h new file mode 100644 index 0000000000..a00659d880 --- /dev/null +++ b/indra/test/debug.h @@ -0,0 +1,68 @@ +/** + * @file   debug.h + * @author Nat Goodspeed + * @date   2009-05-28 + * @brief  Debug output for unit test code + *  + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_DEBUG_H) +#define LL_DEBUG_H + +#include <iostream> + +/***************************************************************************** +*   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. +class Debug +{ +public: +    Debug(const std::string& block): +        mBlock(block) +    { +        (*this)("entry"); +    } + +    ~Debug() +    { +        (*this)("exit"); +    } + +    void operator()(const std::string& status) +    { +#if defined(DEBUG_ON) +        std::cout << mBlock << ' ' << status << std::endl; +#endif +    } + +private: +    const std::string mBlock; +}; + +// It's often convenient to use the name of the enclosing function as the name +// of the Debug block. +#define DEBUG Debug debug(__FUNCTION__) + +// These BEGIN/END macros are specifically for debugging output -- please +// don't assume you must use such for coroutines in general! They only help to +// make control flow (as well as exception exits) explicit. +#define BEGIN                                   \ +{                                               \ +    DEBUG;                                      \ +    try + +#define END                                     \ +    catch (...)                                 \ +    {                                           \ +        debug("*** exceptional ");              \ +        throw;                                  \ +    }                                           \ +} + +#endif /* ! defined(LL_DEBUG_H) */ diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp index e401f89b22..31130c3c79 100644 --- a/indra/test/llevents_tut.cpp +++ b/indra/test/llevents_tut.cpp @@ -32,96 +32,10 @@  // other Linden headers  #include "lltut.h"  #include "stringize.h" +#include "tests/listener.h"  using boost::assign::list_of; -/***************************************************************************** -*   test listener class -*****************************************************************************/ -class Listener; -std::ostream& operator<<(std::ostream&, const Listener&); - -class Listener -{ -public: -    Listener(const std::string& name): -        mName(name) -    { -//      std::cout << *this << ": ctor\n"; -    } -    Listener(const Listener& that): -        mName(that.mName), -        mLastEvent(that.mLastEvent) -    { -//      std::cout << *this << ": copy\n"; -    } -    virtual ~Listener() -    { -//      std::cout << *this << ": dtor\n"; -    } -    std::string getName() const { return mName; } -    bool call(const LLSD& event) -    { -//      std::cout << *this << "::call(" << event << ")\n"; -        mLastEvent = event; -        return false; -    } -    bool callstop(const LLSD& event) -    { -//      std::cout << *this << "::callstop(" << event << ")\n"; -        mLastEvent = event; -        return true; -    } -    LLSD getLastEvent() const -    { -//      std::cout << *this << "::getLastEvent() -> " << mLastEvent << "\n"; -        return mLastEvent; -    } -    void reset(const LLSD& to = LLSD()) -    { -//      std::cout << *this << "::reset(" << to << ")\n"; -        mLastEvent = to; -    } - -private: -    std::string mName; -    LLSD mLastEvent; -}; - -std::ostream& operator<<(std::ostream& out, const Listener& listener) -{ -    out << "Listener(" << listener.getName() /* << "@" << &listener */ << ')'; -    return out; -} - -struct Collect -{ -    bool add(const std::string& bound, const LLSD& event) -    { -        result.push_back(bound); -        return false; -    } -    void clear() { result.clear(); } -    typedef std::vector<std::string> StringList; -    StringList result; -}; - -std::ostream& operator<<(std::ostream& out, const Collect::StringList& strings) -{ -    out << '('; -    Collect::StringList::const_iterator begin(strings.begin()), end(strings.end()); -    if (begin != end) -    { -        out << '"' << *begin << '"'; -        while (++begin != end) -        { -            out << ", \"" << *begin << '"'; -        } -    } -    out << ')'; -    return out; -} -  template<typename T>  T make(const T& value) { return value; } @@ -174,14 +88,7 @@ namespace tut          // default combiner is defined to return the value returned by the          // last listener, which is meaningless if there were no listeners.          per_frame.post(0); -        // NOTE: boost::bind() saves its arguments by VALUE! If you pass an -        // object instance rather than a pointer, you'll end up binding to an -        // internal copy of that instance! Use boost::ref() to capture a -        // reference instead. -        LLBoundListener connection = per_frame.listen(listener0.getName(), -                                                      boost::bind(&Listener::call, -                                                                  boost::ref(listener0), -                                                                  _1)); +        LLBoundListener connection = listener0.listenTo(per_frame);          ensure("connected", connection.connected());          ensure("not blocked", ! connection.blocked());          per_frame.post(1); @@ -207,6 +114,10 @@ namespace tut          bool threw = false;          try          { +            // NOTE: boost::bind() saves its arguments by VALUE! If you pass +            // an object instance rather than a pointer, you'll end up binding +            // to an internal copy of that instance! Use boost::ref() to +            // capture a reference instead.              per_frame.listen(listener0.getName(), // note bug, dup name                               boost::bind(&Listener::call, boost::ref(listener1), _1));          } @@ -221,8 +132,7 @@ namespace tut          }          ensure("threw DupListenerName", threw);          // do it right this time -        per_frame.listen(listener1.getName(), -                         boost::bind(&Listener::call, boost::ref(listener1), _1)); +        listener1.listenTo(per_frame);          per_frame.post(5);          check_listener("got", listener0, 5);          check_listener("got", listener1, 5); @@ -252,16 +162,10 @@ namespace tut          LLEventPump& per_frame(pumps.obtain("per-frame"));          listener0.reset(0);          listener1.reset(0); -        LLBoundListener bound0 = per_frame.listen(listener0.getName(), -                                                  boost::bind(&Listener::callstop, -                                                              boost::ref(listener0), -                                                              _1)); -        LLBoundListener bound1 = per_frame.listen(listener1.getName(), -                                                  boost::bind(&Listener::call, -                                                              boost::ref(listener1), -                                                              _1), -                                                  // after listener0 -                                                  make<LLEventPump::NameList>(list_of(listener0.getName()))); +        LLBoundListener bound0 = listener0.listenTo(per_frame, &Listener::callstop); +        LLBoundListener bound1 = listener1.listenTo(per_frame, &Listener::call, +                                                    // after listener0 +                                                    make<LLEventPump::NameList>(list_of(listener0.getName())));          ensure("enabled", per_frame.enabled());          ensure("connected 0", bound0.connected());          ensure("unblocked 0", ! bound0.blocked()); @@ -301,7 +205,7 @@ namespace tut          // LLEventQueue.          LLEventPump& mainloop(pumps.obtain("mainloop"));          ensure("LLEventQueue leaf class", dynamic_cast<LLEventQueue*>(&login)); -        login.listen(listener0.getName(), boost::bind(&Listener::call, boost::ref(listener0), _1)); +        listener0.listenTo(login);          listener0.reset(0);          login.post(1);          check_listener("waiting for queued event", listener0, 0); @@ -354,11 +258,10 @@ namespace tut      {          set_test_name("stopListening()");          LLEventPump& login(pumps.obtain("login")); -        login.listen(listener0.getName(), boost::bind(&Listener::call, boost::ref(listener0), _1)); +        listener0.listenTo(login);          login.stopListening(listener0.getName());          // should not throw because stopListening() should have removed name -        login.listen(listener0.getName(), -                     boost::bind(&Listener::callstop, boost::ref(listener0), _1)); +        listener0.listenTo(login, &Listener::callstop);          LLBoundListener wrong = login.getListener("bogus");          ensure("bogus connection disconnected", ! wrong.connected());          ensure("bogus connection blocked", wrong.blocked()); @@ -378,10 +281,8 @@ namespace tut                          boost::bind(&LLEventPump::post, boost::ref(filter0), _1));          upstream.listen(filter1.getName(),                          boost::bind(&LLEventPump::post, boost::ref(filter1), _1)); -        filter0.listen(listener0.getName(), -                       boost::bind(&Listener::call, boost::ref(listener0), _1)); -        filter1.listen(listener1.getName(), -                       boost::bind(&Listener::call, boost::ref(listener1), _1)); +        listener0.listenTo(filter0); +        listener1.listenTo(filter1);          listener0.reset(0);          listener1.reset(0);          upstream.post(1); @@ -536,7 +437,7 @@ namespace tut          // Passing a string LLEventPump name to LLListenerOrPumpName          listener0.reset(0);          LLEventStream random("random"); -        random.listen(listener0.getName(), boost::bind(&Listener::call, boost::ref(listener0), _1)); +        listener0.listenTo(random);          eventSource("random");          check_listener("got by pump name", listener0, 17);          bool threw = false; diff --git a/indra/test/llsdmessagebuilder_tut.cpp b/indra/test/llsdmessagebuilder_tut.cpp index 27ab127772..f4457b6d15 100755 --- a/indra/test/llsdmessagebuilder_tut.cpp +++ b/indra/test/llsdmessagebuilder_tut.cpp @@ -44,6 +44,8 @@  #include "v3dmath.h"  #include "v3math.h"  #include "v4math.h" +#include "llsdutil.h" +//#include "llsdutil.cpp"  #include "llsdutil_math.cpp"  #include "lltemplatemessagebuilder.h" diff --git a/indra/test/llsdmessagereader_tut.cpp b/indra/test/llsdmessagereader_tut.cpp index 36cfe5ebfc..f11e148cca 100755 --- a/indra/test/llsdmessagereader_tut.cpp +++ b/indra/test/llsdmessagereader_tut.cpp @@ -42,6 +42,7 @@  #include "message.h"  #include "llsdmessagereader.h"  #include "llsdutil.h" +#include "llsdutil_math.h"  namespace tut  {	 diff --git a/indra/test/llsdutil_tut.cpp b/indra/test/llsdutil_tut.cpp index 0c4bbc2e62..d125bb0005 100644 --- a/indra/test/llsdutil_tut.cpp +++ b/indra/test/llsdutil_tut.cpp @@ -44,12 +44,42 @@  #include "v4math.h"  #include "llquaternion.h"  #include "llsdutil.h" - +#include "llsdutil_math.h" +#include "stringize.h" +#include <set> +#include <boost/range.hpp>  namespace tut  {  	struct llsdutil_data  	{ +        void test_matches(const std::string& proto_key, const LLSD& possibles, +                          const char** begin, const char** end) +        { +            std::set<std::string> succeed(begin, end); +            LLSD prototype(possibles[proto_key]); +            for (LLSD::map_const_iterator pi(possibles.beginMap()), pend(possibles.endMap()); +                 pi != pend; ++pi) +            { +                std::string match(llsd_matches(prototype, pi->second)); +                std::set<std::string>::const_iterator found = succeed.find(pi->first); +                if (found != succeed.end()) +                { +                    // This test is supposed to succeed. Comparing to the +                    // empty string ensures that if the test fails, it will +                    // display the string received so we can tell what failed. +                    ensure_equals("match", match, ""); +                } +                else +                { +                    // This test is supposed to fail. If we get a false match, +                    // the string 'match' will be empty, which doesn't tell us +                    // much about which case went awry. So construct a more +                    // detailed description string. +                    ensure(proto_key + " shouldn't match " + pi->first, ! match.empty()); +                } +            } +        }  	};  	typedef test_group<llsdutil_data> llsdutil_test;;  	typedef llsdutil_test::object llsdutil_object; @@ -159,4 +189,207 @@ namespace tut  		LLSD sd1 = ll_sd_from_color4(c1);  		ensure_equals("sd -> LLColor4 -> sd", sd, sd1);  	} + +    template<> template<> +    void llsdutil_object::test<9>() +    { +        set_test_name("llsd_matches"); + +        // for this test, construct a map of all possible LLSD types +        LLSD map; +        map.insert("empty",     LLSD()); +        map.insert("Boolean",   LLSD::Boolean()); +        map.insert("Integer",   LLSD::Integer(0)); +        map.insert("Real",      LLSD::Real(0.0)); +        map.insert("String",    LLSD::String("bah")); +        map.insert("NumString", LLSD::String("1")); +        map.insert("UUID",      LLSD::UUID()); +        map.insert("Date",      LLSD::Date()); +        map.insert("URI",       LLSD::URI()); +        map.insert("Binary",    LLSD::Binary()); +        map.insert("Map",       LLSD().insert("foo", LLSD())); +        // Only an empty array can be constructed on the fly +        LLSD array; +        array.append(LLSD()); +        map.insert("Array",     array); + +        // These iterators are declared outside our various for loops to avoid +        // fatal MSVC warning: "I used to be broken, but I'm all better now!" +        LLSD::map_const_iterator mi, mend(map.endMap()); + +        /*-------------------------- llsd_matches --------------------------*/ + +        // empty prototype matches anything +        for (mi = map.beginMap(); mi != mend; ++mi) +        { +            ensure_equals(std::string("empty matches ") + mi->first, llsd_matches(LLSD(), mi->second), ""); +        } + +        LLSD proto_array, data_array; +        for (int i = 0; i < 3; ++i) +        { +            proto_array.append(LLSD()); +            data_array.append(LLSD()); +        } + +        // prototype array matches only array +        for (mi = map.beginMap(); mi != mend; ++mi) +        { +            ensure(std::string("array doesn't match ") + mi->first, +                   ! llsd_matches(proto_array, mi->second).empty()); +        } + +        // data array must be at least as long as prototype array +        proto_array.append(LLSD()); +        ensure_equals("data array too short", llsd_matches(proto_array, data_array), +                      "Array size 4 required instead of Array size 3"); +        data_array.append(LLSD()); +        ensure_equals("data array just right", llsd_matches(proto_array, data_array), ""); +        data_array.append(LLSD()); +        ensure_equals("data array longer", llsd_matches(proto_array, data_array), ""); + +        // array element matching +        data_array[0] = LLSD::String(); +        ensure_equals("undefined prototype array entry", llsd_matches(proto_array, data_array), ""); +        proto_array[0] = LLSD::Binary(); +        ensure_equals("scalar prototype array entry", llsd_matches(proto_array, data_array), +                      "[0]: Binary required instead of String"); +        data_array[0] = LLSD::Binary(); +        ensure_equals("matching prototype array entry", llsd_matches(proto_array, data_array), ""); + +        // build a coupla maps +        LLSD proto_map, data_map; +        data_map["got"] = LLSD(); +        data_map["found"] = LLSD(); +        for (LLSD::map_const_iterator dmi(data_map.beginMap()), dmend(data_map.endMap()); +             dmi != dmend; ++dmi) +        { +            proto_map[dmi->first] = dmi->second; +        } +        proto_map["foo"] = LLSD(); +        proto_map["bar"] = LLSD(); + +        // prototype map matches only map +        for (mi = map.beginMap(); mi != mend; ++mi) +        { +            ensure(std::string("map doesn't match ") + mi->first, +                   ! llsd_matches(proto_map, mi->second).empty()); +        } + +        // data map must contain all keys in prototype map +        std::string error(llsd_matches(proto_map, data_map)); +        ensure_contains("missing keys", error, "missing keys"); +        ensure_contains("missing foo", error, "foo"); +        ensure_contains("missing bar", error, "bar"); +        ensure_does_not_contain("found found", error, "found"); +        ensure_does_not_contain("got got", error, "got"); +        data_map["bar"] = LLSD(); +        error = llsd_matches(proto_map, data_map); +        ensure_contains("missing foo", error, "foo"); +        ensure_does_not_contain("got bar", error, "bar"); +        data_map["foo"] = LLSD(); +        ensure_equals("data map just right", llsd_matches(proto_map, data_map), ""); +        data_map["extra"] = LLSD(); +        ensure_equals("data map with extra", llsd_matches(proto_map, data_map), ""); + +        // map element matching +        data_map["foo"] = LLSD::String(); +        ensure_equals("undefined prototype map entry", llsd_matches(proto_map, data_map), ""); +        proto_map["foo"] = LLSD::Binary(); +        ensure_equals("scalar prototype map entry", llsd_matches(proto_map, data_map), +                      "['foo']: Binary required instead of String"); +        data_map["foo"] = LLSD::Binary(); +        ensure_equals("matching prototype map entry", llsd_matches(proto_map, data_map), ""); + +        // String +        { +            static const char* matches[] = { "String", "NumString", "Boolean", "Integer", +                                             "Real", "UUID", "Date", "URI" }; +            test_matches("String", map, boost::begin(matches), boost::end(matches)); +        } + +        // Boolean, Integer, Real +        static const char* numerics[] = { "Boolean", "Integer", "Real" }; +        for (const char **ni = boost::begin(numerics), **nend = boost::end(numerics); +             ni != nend; ++ni) +        { +            static const char* matches[] = { "Boolean", "Integer", "Real", "String", "NumString" }; +            test_matches(*ni, map, boost::begin(matches), boost::end(matches)); +        } + +        // UUID +        { +            static const char* matches[] = { "UUID", "String", "NumString" }; +            test_matches("UUID", map, boost::begin(matches), boost::end(matches)); +        } + +        // Date +        { +            static const char* matches[] = { "Date", "String", "NumString" }; +            test_matches("Date", map, boost::begin(matches), boost::end(matches)); +        } + +        // URI +        { +            static const char* matches[] = { "URI", "String", "NumString" }; +            test_matches("URI", map, boost::begin(matches), boost::end(matches)); +        } + +        // Binary +        { +            static const char* matches[] = { "Binary" }; +            test_matches("Binary", map, boost::begin(matches), boost::end(matches)); +        } + +        /*-------------------------- llsd_equals ---------------------------*/ + +        // Cross-product of each LLSD type with every other +        for (LLSD::map_const_iterator lmi(map.beginMap()), lmend(map.endMap()); +             lmi != lmend; ++lmi) +        { +            for (LLSD::map_const_iterator rmi(map.beginMap()), rmend(map.endMap()); +                 rmi != rmend; ++rmi) +            { +                // Name this test based on the map keys naming the types of +                // interest, e.g "String::Integer". +                // We expect the values (xmi->second) to be equal if and only +                // if the type names (xmi->first) are equal. +                ensure(STRINGIZE(lmi->first << "::" << rmi->first), +                       bool(lmi->first == rmi->first) == +                       bool(llsd_equals(lmi->second, rmi->second))); +            } +        } + +        // Array cases +        LLSD rarray; +        rarray.append(1.0); +        rarray.append(2); +        rarray.append("3"); +        LLSD larray(rarray); +        ensure("llsd_equals(equal arrays)", llsd_equals(larray, rarray)); +        rarray[2] = "4"; +        ensure("llsd_equals(different [2])", ! llsd_equals(larray, rarray)); +        rarray = larray; +        rarray.append(LLSD::Date()); +        ensure("llsd_equals(longer right array)", ! llsd_equals(larray, rarray)); +        rarray = larray; +        rarray.erase(2); +        ensure("llsd_equals(shorter right array)", ! llsd_equals(larray, rarray)); + +        // Map cases +        LLSD rmap; +        rmap["San Francisco"] = 65; +        rmap["Phoenix"] = 92; +        rmap["Boston"] = 77; +        LLSD lmap(rmap); +        ensure("llsd_equals(equal maps)", llsd_equals(lmap, rmap)); +        rmap["Boston"] = 80; +        ensure("llsd_equals(different [\"Boston\"])", ! llsd_equals(lmap, rmap)); +        rmap = lmap; +        rmap["Atlanta"] = 95; +        ensure("llsd_equals(superset right map)", ! llsd_equals(lmap, rmap)); +        rmap = lmap; +        lmap["Seattle"] = 72; +        ensure("llsd_equals(superset left map)", ! llsd_equals(lmap, rmap)); +    }  } diff --git a/indra/test/lltut.cpp b/indra/test/lltut.cpp index 201e174f9c..e4e0de1ff1 100644 --- a/indra/test/lltut.cpp +++ b/indra/test/lltut.cpp @@ -76,9 +76,13 @@ namespace tut  	void ensure_equals(const char* m, const LLSD& actual,  		const LLSD& expected) +    { +        ensure_equals(std::string(m), actual, expected); +    } + +	void ensure_equals(const std::string& msg, const LLSD& actual, +		const LLSD& expected)  	{ -		const std::string& msg = m ? m : ""; -		  		ensure_equals(msg + " type", actual.type(), expected.type());  		switch (actual.type())  		{ @@ -128,7 +132,7 @@ namespace tut  				{  					ensure_equals(msg + " map keys",   						actual_iter->first, expected_iter->first); -					ensure_equals((msg + "[" + actual_iter->first + "]").c_str(), +					ensure_equals(msg + "[" + actual_iter->first + "]",  						actual_iter->second, expected_iter->second);  					++actual_iter;  					++expected_iter; @@ -141,7 +145,7 @@ namespace tut  				for(int i = 0; i < actual.size(); ++i)  				{ -					ensure_equals((msg + llformat("[%d]", i)).c_str(), +					ensure_equals(msg + llformat("[%d]", i),  						actual[i], expected[i]);  				}  				return; diff --git a/indra/test/lltut.h b/indra/test/lltut.h index 47ea9d3f9e..ba3791cbd4 100644 --- a/indra/test/lltut.h +++ b/indra/test/lltut.h @@ -121,6 +121,9 @@ namespace tut  	void ensure_equals(const char* msg,  		const LLSD& actual, const LLSD& expected); + +	void ensure_equals(const std::string& msg, +		const LLSD& actual, const LLSD& expected);  	void ensure_starts_with(const std::string& msg,  		const std::string& actual, const std::string& expectedStart); diff --git a/indra/test/test.cpp b/indra/test/test.cpp index ba81c6e49e..0ba5758e15 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -64,13 +64,14 @@ namespace tut  class LLTestCallback : public tut::callback  {  public: -	LLTestCallback(bool verbose_mode, std::ostream *stream) : +	LLTestCallback(bool verbose_mode, std::ostream *stream, bool wait) :  		mVerboseMode(verbose_mode),  		mTotalTests(0),  		mPassedTests(0),  		mFailedTests(0),  		mSkippedTests(0), -		mStream(stream) +		mStream(stream), +        mWaitAtExit(wait)  	{  	} @@ -137,6 +138,11 @@ public:  		}  		run_completed_(std::cout); +        if(mWaitAtExit) { +            std::cerr << "Waiting for input before exiting..." << std::endl; +	        std::cin.get(); +        } +  		if (mFailedTests > 0)  		{  			exit(1); @@ -176,6 +182,7 @@ protected:  	int mFailedTests;  	int mSkippedTests;  	std::ostream *mStream; +    bool mWaitAtExit;  };  static const apr_getopt_option_t TEST_CL_OPTIONS[] = @@ -328,7 +335,7 @@ int main(int argc, char **argv)  	}  	// run the tests -	LLTestCallback callback(verbose_mode, output); +	LLTestCallback callback(verbose_mode, output, wait_at_exit);  	tut::runner.get().set_callback(&callback);  	if(test_group.empty()) @@ -339,12 +346,6 @@ int main(int argc, char **argv)  	{  		tut::runner.get().run_tests(test_group);  	} - -	if (wait_at_exit) -	{ -		std::cerr << "Waiting for input before exiting..." << std::endl; -		std::cin.get(); -	}  	if (output)  	{ | 
