diff options
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/llrand.cpp | 104 | ||||
-rw-r--r-- | indra/llcommon/tests/llleap_test.cpp | 25 | ||||
-rw-r--r-- | indra/llcommon/tests/llprocess_test.cpp | 70 |
3 files changed, 99 insertions, 100 deletions
diff --git a/indra/llcommon/llrand.cpp b/indra/llcommon/llrand.cpp index 1b6963a9dd..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+1); -#else - return drand48(); -#endif -} -inline F32 ll_internal_random_float() -{ -#if LL_WINDOWS - return (F32)rand() / (F32)(RAND_MAX+1); -#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 0fc741d9e1..e9edd165df 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -17,7 +17,6 @@ // std headers #include <functional> // external library headers -#include <boost/assign/list_of.hpp> // other Linden headers #include "../test/lltut.h" #include "../test/namedtempfile.h" @@ -29,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) @@ -217,9 +212,9 @@ namespace tut "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. @@ -249,7 +244,7 @@ namespace tut "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!"); } @@ -264,7 +259,7 @@ namespace tut "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!"); } @@ -278,7 +273,7 @@ namespace tut "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:"); } @@ -390,7 +385,8 @@ namespace tut "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())))); + waitfor(LLLeap::create(get_test_name(), + StringVec{PYTHON, script.getName()})); result.ensure(); } @@ -449,7 +445,7 @@ namespace tut " 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()))), + waitfor(LLLeap::create(get_test_name(), StringVec{PYTHON, script.getName()}), 300); // needs more realtime than most tests result.ensure(); } @@ -516,10 +512,7 @@ namespace tut " (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 4adb8d872a..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. @@ -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; }; /***************************************************************************** @@ -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<> |