diff options
Diffstat (limited to 'indra/llcommon')
| -rw-r--r-- | indra/llcommon/llprocessor.cpp | 2 | ||||
| -rw-r--r-- | indra/llcommon/llrand.cpp | 104 | ||||
| -rw-r--r-- | indra/llcommon/tests/llleap_test.cpp | 254 | ||||
| -rw-r--r-- | indra/llcommon/tests/llprocess_test.cpp | 74 | ||||
| -rw-r--r-- | indra/llcommon/tests/llsdserialize_test.cpp | 22 | ||||
| -rw-r--r-- | indra/llcommon/tests/workqueue_test.cpp | 6 | 
6 files changed, 229 insertions, 233 deletions
| diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 4a1a81f083..28f8bc2b93 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -746,7 +746,7 @@ private:  		__cpuid(0x1, eax, ebx, ecx, edx);  		if(feature_infos[0] != (S32)edx)  		{ -			LL_ERRS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL; +			LL_WARNS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL;  		}   #endif // LL_RELEASE_FOR_DOWNLOAD 	 diff --git a/indra/llcommon/llrand.cpp b/indra/llcommon/llrand.cpp index cb28a8f5c3..33afc50cf7 100644 --- a/indra/llcommon/llrand.cpp +++ b/indra/llcommon/llrand.cpp @@ -58,46 +58,14 @@   * to restore uniform distribution.   */ -// *NOTE: The system rand implementation is probably not correct. -#define LL_USE_SYSTEM_RAND 0 +static LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed()); -#if LL_USE_SYSTEM_RAND -#include <cstdlib> -#endif +// no default implementation, only specific F64 and F32 specializations +template <typename REAL> +inline REAL ll_internal_random(); -#if LL_USE_SYSTEM_RAND -class LLSeedRand -{ -public: -	LLSeedRand() -	{ -#if LL_WINDOWS -		srand(LLUUID::getRandomSeed()); -#else -		srand48(LLUUID::getRandomSeed()); -#endif -	} -}; -static LLSeedRand sRandomSeeder; -inline F64 ll_internal_random_double() -{ -#if LL_WINDOWS -	return (F64)rand() / (F64)RAND_MAX;  -#else -	return drand48(); -#endif -} -inline F32 ll_internal_random_float() -{ -#if LL_WINDOWS -	return (F32)rand() / (F32)RAND_MAX;  -#else -	return (F32)drand48(); -#endif -} -#else -static LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed()); -inline F64 ll_internal_random_double() +template <> +inline F64 ll_internal_random<F64>()  {  	// *HACK: Through experimentation, we have found that dual core  	// CPUs (or at least multi-threaded processes) seem to @@ -108,15 +76,35 @@ inline F64 ll_internal_random_double()  	return rv;  } +template <> +inline F32 ll_internal_random<F32>() +{ +    return F32(ll_internal_random<F64>()); +} + +/*------------------------------ F64 aliases -------------------------------*/ +inline F64 ll_internal_random_double() +{ +    return ll_internal_random<F64>(); +} + +F64 ll_drand() +{ +	return ll_internal_random_double(); +} + +/*------------------------------ F32 aliases -------------------------------*/  inline F32 ll_internal_random_float()  { -	// The clamping rules are described above. -	F32 rv = (F32)gRandomGenerator(); -	if(!((rv >= 0.0f) && (rv < 1.0f))) return fmod(rv, 1.f); -	return rv; +    return ll_internal_random<F32>(); +} + +F32 ll_frand() +{ +	return ll_internal_random_float();  } -#endif +/*-------------------------- clamped random range --------------------------*/  S32 ll_rand()  {  	return ll_rand(RAND_MAX); @@ -130,42 +118,28 @@ S32 ll_rand(S32 val)  	return rv;  } -F32 ll_frand() -{ -	return ll_internal_random_float(); -} - -F32 ll_frand(F32 val) +template <typename REAL> +REAL ll_grand(REAL val)  {  	// The clamping rules are described above. -	F32 rv = ll_internal_random_float() * val; +	REAL rv = ll_internal_random<REAL>() * val;  	if(val > 0)  	{ -		if(rv >= val) return 0.0f; +		if(rv >= val) return REAL();  	}  	else  	{ -		if(rv <= val) return 0.0f; +		if(rv <= val) return REAL();  	}  	return rv;  } -F64 ll_drand() +F32 ll_frand(F32 val)  { -	return ll_internal_random_double(); +    return ll_grand<F32>(val);  }  F64 ll_drand(F64 val)  { -	// The clamping rules are described above. -	F64 rv = ll_internal_random_double() * val; -	if(val > 0) -	{ -		if(rv >= val) return 0.0; -	} -	else -	{ -		if(rv <= val) return 0.0; -	} -	return rv; +    return ll_grand<F64>(val);  } diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index 7ee36a9ea6..e9edd165df 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -17,8 +17,6 @@  // std headers  #include <functional>  // external library headers -#include <boost/assign/list_of.hpp> -#include <boost/phoenix/core/argument.hpp>  // other Linden headers  #include "../test/lltut.h"  #include "../test/namedtempfile.h" @@ -30,10 +28,6 @@  #include "stringize.h"  #include "StringVec.h" -using boost::assign::list_of; - -StringVec sv(const StringVec& listof) { return listof; } -  #if defined(LL_WINDOWS)  #define sleep(secs) _sleep((secs) * 1000) @@ -104,12 +98,12 @@ namespace tut          llleap_data():              reader(".py",                     // This logic is adapted from vita.viewerclient.receiveEvent() -                   boost::phoenix::placeholders::arg1 << +                   [](std::ostream& out){ out <<                     "import re\n"                     "import os\n"                     "import sys\n"                     "\n" -                   "from llbase import llsd\n" +                   "import llsd\n"                     "\n"                     "class ProtocolError(Exception):\n"                     "    def __init__(self, msg, data):\n" @@ -188,7 +182,7 @@ namespace tut                     "def request(pump, data):\n"                     "    # we expect 'data' is a dict\n"                     "    data['reply'] = _reply\n" -                   "    send(pump, data)\n"), +                   "    send(pump, data)\n";}),              // Get the actual pathname of the NamedExtTempFile and trim off              // the ".py" extension. (We could cache reader.getName() in a              // separate member variable, but I happen to know getName() just @@ -213,14 +207,14 @@ namespace tut      void object::test<1>()      {          set_test_name("multiple LLLeap instances"); -        NamedTempFile script("py", -                             "import time\n" -                             "time.sleep(1)\n"); +        NamedExtTempFile script("py", +                                "import time\n" +                                "time.sleep(1)\n");          LLLeapVector instances;          instances.push_back(LLLeap::create(get_test_name(), -                                           sv(list_of(PYTHON)(script.getName())))->getWeak()); +                                           StringVec{PYTHON, script.getName()})->getWeak());          instances.push_back(LLLeap::create(get_test_name(), -                                           sv(list_of(PYTHON)(script.getName())))->getWeak()); +                                           StringVec{PYTHON, script.getName()})->getWeak());          // In this case we're simply establishing that two LLLeap instances          // can coexist without throwing exceptions or bombing in any other          // way. Wait for them to terminate. @@ -231,10 +225,10 @@ namespace tut      void object::test<2>()      {          set_test_name("stderr to log"); -        NamedTempFile script("py", -                             "import sys\n" -                             "sys.stderr.write('''Hello from Python!\n" -                             "note partial line''')\n"); +        NamedExtTempFile script("py", +                                "import sys\n" +                                "sys.stderr.write('''Hello from Python!\n" +                                "note partial line''')\n");          StringVec vcommand{ PYTHON, script.getName() };          CaptureLog log(LLError::LEVEL_INFO);          waitfor(LLLeap::create(get_test_name(), vcommand)); @@ -246,11 +240,11 @@ namespace tut      void object::test<3>()      {          set_test_name("bad stdout protocol"); -        NamedTempFile script("py", -                             "print('Hello from Python!')\n"); +        NamedExtTempFile script("py", +                                "print('Hello from Python!')\n");          CaptureLog log(LLError::LEVEL_WARN);          waitfor(LLLeap::create(get_test_name(), -                               sv(list_of(PYTHON)(script.getName())))); +                               StringVec{PYTHON, script.getName()}));          ensure_contains("error log line",                          log.messageWith("invalid protocol"), "Hello from Python!");      } @@ -259,13 +253,13 @@ namespace tut      void object::test<4>()      {          set_test_name("leftover stdout"); -        NamedTempFile script("py", -                             "import sys\n" -                             // note lack of newline -                             "sys.stdout.write('Hello from Python!')\n"); +        NamedExtTempFile script("py", +                                "import sys\n" +                                // note lack of newline +                                "sys.stdout.write('Hello from Python!')\n");          CaptureLog log(LLError::LEVEL_WARN);          waitfor(LLLeap::create(get_test_name(), -                               sv(list_of(PYTHON)(script.getName())))); +                               StringVec{PYTHON, script.getName()}));          ensure_contains("error log line",                          log.messageWith("Discarding"), "Hello from Python!");      } @@ -274,12 +268,12 @@ namespace tut      void object::test<5>()      {          set_test_name("bad stdout len prefix"); -        NamedTempFile script("py", -                             "import sys\n" -                             "sys.stdout.write('5a2:something')\n"); +        NamedExtTempFile script("py", +                                "import sys\n" +                                "sys.stdout.write('5a2:something')\n");          CaptureLog log(LLError::LEVEL_WARN);          waitfor(LLLeap::create(get_test_name(), -                               sv(list_of(PYTHON)(script.getName())))); +                               StringVec{PYTHON, script.getName()}));          ensure_contains("error log line",                          log.messageWith("invalid protocol"), "5a2:");      } @@ -381,17 +375,18 @@ namespace tut          set_test_name("round trip");          AckAPI api;          Result result; -        NamedTempFile script("py", -                             boost::phoenix::placeholders::arg1 << -                             "from " << reader_module << " import *\n" -                             // make a request on our little API -                             "request(pump='" << api.getName() << "', data={})\n" -                             // wait for its response -                             "resp = get()\n" -                             "result = '' if resp == dict(pump=replypump(), data='ack')\\\n" -                             "            else 'bad: ' + str(resp)\n" -                             "send(pump='" << result.getName() << "', data=result)\n"); -        waitfor(LLLeap::create(get_test_name(), sv(list_of(PYTHON)(script.getName())))); +        NamedExtTempFile script("py", +                                [&](std::ostream& out){ out << +                                "from " << reader_module << " import *\n" +                                // make a request on our little API +                                "request(pump='" << api.getName() << "', data={})\n" +                                // wait for its response +                                "resp = get()\n" +                                "result = '' if resp == dict(pump=replypump(), data='ack')\\\n" +                                "            else 'bad: ' + str(resp)\n" +                                "send(pump='" << result.getName() << "', data=result)\n";}); +        waitfor(LLLeap::create(get_test_name(), +                               StringVec{PYTHON, script.getName()}));          result.ensure();      } @@ -419,38 +414,38 @@ namespace tut          // iterations etc. in OS pipes and the LLLeap/LLProcess implementation.          ReqIDAPI api;          Result result; -        NamedTempFile script("py", -                             boost::phoenix::placeholders::arg1 << -                             "import sys\n" -                             "from " << reader_module << " import *\n" -                             // Note that since reader imports llsd, this -                             // 'import *' gets us llsd too. -                             "sample = llsd.format_notation(dict(pump='" << -                             api.getName() << "', data=dict(reqid=999999, reply=replypump())))\n" -                             // The whole packet has length prefix too: "len:data" -                             "samplen = len(str(len(sample))) + 1 + len(sample)\n" -                             // guess how many messages it will take to -                             // accumulate BUFFERED_LENGTH -                             "count = int(" << BUFFERED_LENGTH << "/samplen)\n" -                             "print('Sending %s requests' % count, file=sys.stderr)\n" -                             "for i in range(count):\n" -                             "    request('" << api.getName() << "', dict(reqid=i))\n" -                             // The assumption in this specific test that -                             // replies will arrive in the same order as -                             // requests is ONLY valid because the API we're -                             // invoking sends replies instantly. If the API -                             // had to wait for some external event before -                             // sending its reply, replies could arrive in -                             // arbitrary order, and we'd have to tick them -                             // off from a set. -                             "result = ''\n" -                             "for i in range(count):\n" -                             "    resp = get()\n" -                             "    if resp['data']['reqid'] != i:\n" -                             "        result = 'expected reqid=%s in %s' % (i, resp)\n" -                             "        break\n" -                             "send(pump='" << result.getName() << "', data=result)\n"); -        waitfor(LLLeap::create(get_test_name(), sv(list_of(PYTHON)(script.getName()))), +        NamedExtTempFile script("py", +                                [&](std::ostream& out){ out << +                                "import sys\n" +                                "from " << reader_module << " import *\n" +                                // Note that since reader imports llsd, this +                                // 'import *' gets us llsd too. +                                "sample = llsd.format_notation(dict(pump='" << +                                api.getName() << "', data=dict(reqid=999999, reply=replypump())))\n" +                                // The whole packet has length prefix too: "len:data" +                                "samplen = len(str(len(sample))) + 1 + len(sample)\n" +                                // guess how many messages it will take to +                                // accumulate BUFFERED_LENGTH +                                "count = int(" << BUFFERED_LENGTH << "/samplen)\n" +                                "print('Sending %s requests' % count, file=sys.stderr)\n" +                                "for i in range(count):\n" +                                "    request('" << api.getName() << "', dict(reqid=i))\n" +                                // The assumption in this specific test that +                                // replies will arrive in the same order as +                                // requests is ONLY valid because the API we're +                                // invoking sends replies instantly. If the API +                                // had to wait for some external event before +                                // sending its reply, replies could arrive in +                                // arbitrary order, and we'd have to tick them +                                // off from a set. +                                "result = ''\n" +                                "for i in range(count):\n" +                                "    resp = get()\n" +                                "    if resp['data']['reqid'] != i:\n" +                                "        result = 'expected reqid=%s in %s' % (i, resp)\n" +                                "        break\n" +                                "send(pump='" << result.getName() << "', data=result)\n";}); +        waitfor(LLLeap::create(get_test_name(), StringVec{PYTHON, script.getName()}),                  300);               // needs more realtime than most tests          result.ensure();      } @@ -462,65 +457,62 @@ namespace tut      {          ReqIDAPI api;          Result result; -        NamedTempFile script("py", -                             boost::phoenix::placeholders::arg1 << -                             "import sys\n" -                             "from " << reader_module << " import *\n" -                             // Generate a very large string value. -                             "desired = int(sys.argv[1])\n" -                             // 7 chars per item: 6 digits, 1 comma -                             "count = int((desired - 50)/7)\n" -                             "large = ''.join('%06d,' % i for i in range(count))\n" -                             // Pass 'large' as reqid because we know the API -                             // will echo reqid, and we want to receive it back. -                             "request('" << api.getName() << "', dict(reqid=large))\n" -                             "try:\n" -                             "    resp = get()\n" -                             "except ParseError as e:\n" -                             "    # try to find where e.data diverges from expectation\n" -                             // Normally we'd expect a 'pump' key in there, -                             // too, with value replypump(). But Python -                             // serializes keys in a different order than C++, -                             // so incoming data start with 'data'. -                             // Truthfully, though, if we get as far as 'pump' -                             // before we find a difference, something's very -                             // strange. -                             "    expect = llsd.format_notation(dict(data=dict(reqid=large)))\n" -                             "    chunk = 40\n" -                             "    for offset in range(0, max(len(e.data), len(expect)), chunk):\n" -                             "        if e.data[offset:offset+chunk] != \\\n" -                             "           expect[offset:offset+chunk]:\n" -                             "            print('Offset %06d: expect %r,\\n'\\\n" -                             "                                '                  get %r' %\\\n" -                             "                                (offset,\n" -                             "                                 expect[offset:offset+chunk],\n" -                             "                                 e.data[offset:offset+chunk]),\n" -                             "                                 file=sys.stderr)\n" -                             "            break\n" -                             "    else:\n" -                             "        print('incoming data matches expect?!', file=sys.stderr)\n" -                             "    send('" << result.getName() << "', '%s: %s' % (e.__class__.__name__, e))\n" -                             "    sys.exit(1)\n" -                             "\n" -                             "echoed = resp['data']['reqid']\n" -                             "if echoed == large:\n" -                             "    send('" << result.getName() << "', '')\n" -                             "    sys.exit(0)\n" -                             // Here we know echoed did NOT match; try to find where -                             "for i in range(count):\n" -                             "    start = 7*i\n" -                             "    end   = 7*(i+1)\n" -                             "    if end > len(echoed)\\\n" -                             "    or echoed[start:end] != large[start:end]:\n" -                             "        send('" << result.getName() << "',\n" -                             "             'at offset %s, expected %r but got %r' %\n" -                             "             (start, large[start:end], echoed[start:end]))\n" -                             "sys.exit(1)\n"); +        NamedExtTempFile script("py", +                                [&](std::ostream& out){ out << +                                "import sys\n" +                                "from " << reader_module << " import *\n" +                                // Generate a very large string value. +                                "desired = int(sys.argv[1])\n" +                                // 7 chars per item: 6 digits, 1 comma +                                "count = int((desired - 50)/7)\n" +                                "large = ''.join('%06d,' % i for i in range(count))\n" +                                // Pass 'large' as reqid because we know the API +                                // will echo reqid, and we want to receive it back. +                                "request('" << api.getName() << "', dict(reqid=large))\n" +                                "try:\n" +                                "    resp = get()\n" +                                "except ParseError as e:\n" +                                "    # try to find where e.data diverges from expectation\n" +                                // Normally we'd expect a 'pump' key in there, +                                // too, with value replypump(). But Python +                                // serializes keys in a different order than C++, +                                // so incoming data start with 'data'. +                                // Truthfully, though, if we get as far as 'pump' +                                // before we find a difference, something's very +                                // strange. +                                "    expect = llsd.format_notation(dict(data=dict(reqid=large)))\n" +                                "    chunk = 40\n" +                                "    for offset in range(0, max(len(e.data), len(expect)), chunk):\n" +                                "        if e.data[offset:offset+chunk] != \\\n" +                                "           expect[offset:offset+chunk]:\n" +                                "            print('Offset %06d: expect %r,\\n'\\\n" +                                "                                '                  get %r' %\\\n" +                                "                                (offset,\n" +                                "                                 expect[offset:offset+chunk],\n" +                                "                                 e.data[offset:offset+chunk]),\n" +                                "                                 file=sys.stderr)\n" +                                "            break\n" +                                "    else:\n" +                                "        print('incoming data matches expect?!', file=sys.stderr)\n" +                                "    send('" << result.getName() << "', '%s: %s' % (e.__class__.__name__, e))\n" +                                "    sys.exit(1)\n" +                                "\n" +                                "echoed = resp['data']['reqid']\n" +                                "if echoed == large:\n" +                                "    send('" << result.getName() << "', '')\n" +                                "    sys.exit(0)\n" +                                // Here we know echoed did NOT match; try to find where +                                "for i in range(count):\n" +                                "    start = 7*i\n" +                                "    end   = 7*(i+1)\n" +                                "    if end > len(echoed)\\\n" +                                "    or echoed[start:end] != large[start:end]:\n" +                                "        send('" << result.getName() << "',\n" +                                "             'at offset %s, expected %r but got %r' %\n" +                                "             (start, large[start:end], echoed[start:end]))\n" +                                "sys.exit(1)\n";});          waitfor(LLLeap::create(test_name, -                               sv(list_of -                                  (PYTHON) -                                  (script.getName()) -                                  (stringize(size)))), +                               StringVec{PYTHON, script.getName(), stringize(size)}),                  180);               // try a longer timeout          result.ensure();      } diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index 81449b4a42..b6b297b8d7 100644 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -151,8 +151,38 @@ struct PythonProcessLauncher      /// Launch Python script; verify that it launched      void launch()      { -        mPy = LLProcess::create(mParams); -        tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), bool(mPy)); +        try +        { +            mPy = LLProcess::create(mParams); +            tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), bool(mPy)); +        } +        catch (const tut::failure&) +        { +            // On Windows, if APR_LOG is set, our version of APR's +            // apr_create_proc() logs to the specified file. If this test +            // failed, try to report that log. +            const char* APR_LOG = getenv("APR_LOG"); +            if (APR_LOG && *APR_LOG) +            { +                std::ifstream inf(APR_LOG); +                if (! inf.is_open()) +                { +                    LL_WARNS() << "Couldn't open '" << APR_LOG << "'" << LL_ENDL; +                } +                else +                { +                    LL_WARNS() << "==============================" << LL_ENDL; +                    LL_WARNS() << "From '" << APR_LOG << "':" << LL_ENDL; +                    std::string line; +                    while (std::getline(inf, line)) +                    { +                        LL_WARNS() << line << LL_ENDL; +                    } +                    LL_WARNS() << "==============================" << LL_ENDL; +                } +            } +            throw; +        }      }      /// Run Python script and wait for it to complete. @@ -191,7 +221,7 @@ struct PythonProcessLauncher      LLProcess::Params mParams;      LLProcessPtr mPy;      std::string mDesc; -    NamedTempFile mScript; +    NamedExtTempFile mScript;  };  /// convenience function for PythonProcessLauncher::run() @@ -214,30 +244,26 @@ static std::string python_out(const std::string& desc, const CONTENT& script)  class NamedTempDir: public boost::noncopyable  {  public: -    // Use python() function to create a temp directory: I've found -    // nothing in either Boost.Filesystem or APR quite like Python's -    // tempfile.mkdtemp(). -    // Special extra bonus: on Mac, mkdtemp() reports a pathname -    // starting with /var/folders/something, whereas that's really a -    // symlink to /private/var/folders/something. Have to use -    // realpath() to compare properly.      NamedTempDir(): -        mPath(python_out("mkdtemp()", -                         "from __future__ import with_statement\n" -                         "import os.path, sys, tempfile\n" -                         "with open(sys.argv[1], 'w') as f:\n" -                         "    f.write(os.path.normcase(os.path.normpath(os.path.realpath(tempfile.mkdtemp()))))\n")) -    {} +        mPath(NamedTempFile::temp_path()), +        mCreated(boost::filesystem::create_directories(mPath)) +    { +        mPath = boost::filesystem::canonical(mPath); +    }      ~NamedTempDir()      { -        aprchk(apr_dir_remove(mPath.c_str(), gAPRPoolp)); +        if (mCreated) +        { +            boost::filesystem::remove_all(mPath); +        }      } -    std::string getName() const { return mPath; } +    std::string getName() const { return mPath.string(); }  private: -    std::string mPath; +    boost::filesystem::path mPath; +    bool mCreated;  };  /***************************************************************************** @@ -355,7 +381,7 @@ namespace tut          set_test_name("raw APR nonblocking I/O");          // Create a script file in a temporary place. -        NamedTempFile script("py", +        NamedExtTempFile script("py",              "from __future__ import print_function" EOL              "import sys" EOL              "import time" EOL @@ -565,7 +591,13 @@ namespace tut                                   "    f.write(os.path.normcase(os.path.normpath(os.getcwd())))\n");          // Before running, call setWorkingDirectory()          py.mParams.cwd = tempdir.getName(); -        ensure_equals("os.getcwd()", py.run_read(), tempdir.getName()); +        std::string expected{ tempdir.getName() }; +#if LL_WINDOWS +        // SIGH, don't get tripped up by "C:" != "c:" -- +        // but on the Mac, using tolower() fails because "/users" != "/Users"! +        expected = utf8str_tolower(expected); +#endif +        ensure_equals("os.getcwd()", py.run_read(), expected);      }      template<> template<> diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index 5dbcf4c9b8..08bf7fbc51 100644 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -45,12 +45,6 @@ typedef U32 uint32_t;  #endif  #include "boost/range.hpp" -#include "boost/foreach.hpp" -#include "boost/function.hpp" -#include "boost/bind.hpp" -#include "boost/phoenix/bind/bind_function.hpp" -#include "boost/phoenix/core/argument.hpp" -using namespace boost::phoenix;  #include "../llsd.h"  #include "../llsdserialize.h" @@ -1706,7 +1700,7 @@ namespace tut              // scanner.              import_llsd("import os.path\n"                          "import sys\n" -                        "from llbase import llsd\n") +                        "import llsd\n")          {}          ~TestPythonCompatible() {} @@ -1801,7 +1795,7 @@ namespace tut      // helper for test<3>      static void writeLLSDArray(std::ostream& out, const LLSD& array)      { -        BOOST_FOREACH(LLSD item, llsd::inArray(array)) +        for (const LLSD& item: llsd::inArray(array))          {              LLSDSerialize::toNotation(item, out);              // It's important to separate with newlines because Python's llsd @@ -1841,21 +1835,21 @@ namespace tut          // Create an llsdXXXXXX file containing 'data' serialized to          // notation.          NamedTempFile file("llsd", -                           // NamedTempFile's boost::function constructor +                           // NamedTempFile's function constructor                             // takes a callable. To this callable it passes the                             // std::ostream with which it's writing the                             // NamedTempFile. -                           boost::bind(writeLLSDArray, _1, cdata)); +                           [&](std::ostream& out){ writeLLSDArray(out, cdata); });          python("read C++ notation", -               placeholders::arg1 << +               [&](std::ostream& out){ out <<                 import_llsd <<                 "def parse_each(iterable):\n"                 "    for item in iterable:\n"                 "        yield llsd.parse(item)\n" <<                 pydata <<                 // Don't forget raw-string syntax for Windows pathnames. -               "verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n"); +               "verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n";});      }      template<> template<> @@ -1869,7 +1863,7 @@ namespace tut          NamedTempFile file("llsd", "");          python("write Python notation", -               placeholders::arg1 << +               [&](std::ostream& out){ out <<                 import_llsd <<                 "DATA = [\n"                 "    17,\n" @@ -1883,7 +1877,7 @@ namespace tut                 // N.B. Using 'print' implicitly adds newlines.                 "with open(r'" << file.getName() << "', 'w') as f:\n"                 "    for item in DATA:\n" -               "        print(llsd.format_notation(item).decode(), file=f)\n"); +               "        print(llsd.format_notation(item).decode(), file=f)\n";});          std::ifstream inf(file.getName().c_str());          LLSD item; diff --git a/indra/llcommon/tests/workqueue_test.cpp b/indra/llcommon/tests/workqueue_test.cpp index 1d73f7aa0d..7655a7aa1f 100644 --- a/indra/llcommon/tests/workqueue_test.cpp +++ b/indra/llcommon/tests/workqueue_test.cpp @@ -83,7 +83,11 @@ namespace tut          // signal the work item that it can quit; consider LLOneShotCond.          LLCond<Shared> data;          auto start = WorkQueue::TimePoint::clock::now(); -        auto interval = 100ms; +        // 2s seems like a long time to wait, since it directly impacts the +        // duration of this test program. Unfortunately GitHub's Mac runners +        // are pretty wimpy, and we're getting spurious "too late" errors just +        // because the thread doesn't wake up as soon as we want. +        auto interval = 2s;          queue.postEvery(              interval,              [&data, count = 0] | 
