summaryrefslogtreecommitdiff
path: root/indra/test
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2024-04-25 09:13:23 -0400
committerNat Goodspeed <nat@lindenlab.com>2024-04-25 09:13:23 -0400
commitf162693a23fe5cfda8dab3857718624033812d30 (patch)
tree0768f9ea570b248b48e4caa33103e3d55c625466 /indra/test
parentd8931c9269a90cd01f6f6ff4de83b8fb41df11d3 (diff)
parentd98fc504a1d4bc292ba86acdda053c8b4598a193 (diff)
Merge Maint YZ branch 'main' into DRTVWR-588-cleanup-timers
Diffstat (limited to 'indra/test')
-rw-r--r--indra/test/CMakeLists.txt7
-rw-r--r--indra/test/hexdump.h97
-rw-r--r--indra/test/io.cpp10
-rw-r--r--indra/test/llevents_tut.cpp4
-rw-r--r--indra/test/namedtempfile.h29
-rw-r--r--indra/test/test.cpp38
6 files changed, 156 insertions, 29 deletions
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index b7a39a7450..4a0a8716c4 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -74,6 +74,13 @@ if (WINDOWS)
LINK_FLAGS "/NODEFAULTLIB:LIBCMT"
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
)
+elseif (DARWIN)
+ # Support our "@executable_path/../Resources" load path for our test
+ # executable. This SHOULD properly be "$<TARGET_FILE_DIR:lltest>/Resources",
+ # but the CMake $<TARGET_FILE_DIR> generator expression isn't evaluated by
+ # CREATE_LINK, so fudge it.
+ file(CREATE_LINK "../sharedlibs/Release/Resources" "${CMAKE_BINARY_DIR}/test/Resources"
+ SYMBOLIC)
endif (WINDOWS)
set(TEST_EXE $<TARGET_FILE:lltest>)
diff --git a/indra/test/hexdump.h b/indra/test/hexdump.h
new file mode 100644
index 0000000000..dd7cbaaa3c
--- /dev/null
+++ b/indra/test/hexdump.h
@@ -0,0 +1,97 @@
+/**
+ * @file hexdump.h
+ * @author Nat Goodspeed
+ * @date 2023-09-08
+ * @brief Provide hexdump() and hexmix() ostream formatters
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Copyright (c) 2023, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_HEXDUMP_H)
+#define LL_HEXDUMP_H
+
+#include <cctype>
+#include <iomanip>
+#include <iostream>
+#include <string_view>
+
+// Format a given byte string as 2-digit hex values, no separators
+// Usage: std::cout << hexdump(somestring) << ...
+class hexdump
+{
+public:
+ hexdump(const std::string_view& data):
+ hexdump(data.data(), data.length())
+ {}
+
+ hexdump(const char* data, size_t len):
+ hexdump(reinterpret_cast<const unsigned char*>(data), len)
+ {}
+
+ hexdump(const unsigned char* data, size_t len):
+ mData(data, data + len)
+ {}
+
+ friend std::ostream& operator<<(std::ostream& out, const hexdump& self)
+ {
+ auto oldfmt{ out.flags() };
+ auto oldfill{ out.fill() };
+ out.setf(std::ios_base::hex, std::ios_base::basefield);
+ out.fill('0');
+ for (auto c : self.mData)
+ {
+ out << std::setw(2) << unsigned(c);
+ }
+ out.setf(oldfmt, std::ios_base::basefield);
+ out.fill(oldfill);
+ return out;
+ }
+
+private:
+ std::vector<unsigned char> mData;
+};
+
+// Format a given byte string as a mix of printable characters and, for each
+// non-printable character, "\xnn"
+// Usage: std::cout << hexmix(somestring) << ...
+class hexmix
+{
+public:
+ hexmix(const std::string_view& data):
+ mData(data)
+ {}
+
+ hexmix(const char* data, size_t len):
+ mData(data, len)
+ {}
+
+ friend std::ostream& operator<<(std::ostream& out, const hexmix& self)
+ {
+ auto oldfmt{ out.flags() };
+ auto oldfill{ out.fill() };
+ out.setf(std::ios_base::hex, std::ios_base::basefield);
+ out.fill('0');
+ for (auto c : self.mData)
+ {
+ // std::isprint() must be passed an unsigned char!
+ if (std::isprint(static_cast<unsigned char>(c)))
+ {
+ out << c;
+ }
+ else
+ {
+ out << "\\x" << std::setw(2) << unsigned(c);
+ }
+ }
+ out.setf(oldfmt, std::ios_base::basefield);
+ out.fill(oldfill);
+ return out;
+ }
+
+private:
+ std::string mData;
+};
+
+#endif /* ! defined(LL_HEXDUMP_H) */
diff --git a/indra/test/io.cpp b/indra/test/io.cpp
index 40243a8ad6..99b49c8b29 100644
--- a/indra/test/io.cpp
+++ b/indra/test/io.cpp
@@ -946,7 +946,7 @@ namespace tut
typedef LLCloneIOFactory<LLPipeStringInjector> emitter_t;
emitter_t* emitter = new emitter_t(
new LLPipeStringInjector("suckers never play me"));
- boost::shared_ptr<LLChainIOFactory> factory(emitter);
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
LLIOServerSocket* server = new LLIOServerSocket(
mPool,
mSocket,
@@ -993,7 +993,7 @@ namespace tut
LLPumpIO::chain_t chain;
typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
- boost::shared_ptr<LLChainIOFactory> factory(emitter);
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
LLIOServerSocket* server = new LLIOServerSocket(
mPool,
mSocket,
@@ -1036,7 +1036,7 @@ namespace tut
LLPumpIO::chain_t chain;
typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
- boost::shared_ptr<LLChainIOFactory> factory(emitter);
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
LLIOServerSocket* server = new LLIOServerSocket(
mPool,
mSocket,
@@ -1079,7 +1079,7 @@ namespace tut
LLPumpIO::chain_t chain;
typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
- boost::shared_ptr<LLChainIOFactory> factory(emitter);
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
LLIOServerSocket* server = new LLIOServerSocket(
mPool,
mSocket,
@@ -1120,7 +1120,7 @@ namespace tut
LLPumpIO::chain_t chain;
typedef LLCloneIOFactory<LLIOSleeper> sleeper_t;
sleeper_t* sleeper = new sleeper_t(new LLIOSleeper);
- boost::shared_ptr<LLChainIOFactory> factory(sleeper);
+ std::shared_ptr<LLChainIOFactory> factory(sleeper);
LLIOServerSocket* server = new LLIOServerSocket(
mPool,
mSocket,
diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp
index 17f64a4953..a38de71e48 100644
--- a/indra/test/llevents_tut.cpp
+++ b/indra/test/llevents_tut.cpp
@@ -368,10 +368,10 @@ void events_object::test<7>()
LLEventStream bob("bob"); // should work, previous one unregistered
LLEventStream bob1("bob", true);// allowed to tweak name
ensure_equals("tweaked LLEventStream name", bob1.getName(), "bob1");
- std::vector<boost::shared_ptr<LLEventStream> > streams;
+ std::vector<std::shared_ptr<LLEventStream> > streams;
for (int i = 2; i <= 10; ++i)
{
- streams.push_back(boost::shared_ptr<LLEventStream>(new LLEventStream("bob", true)));
+ streams.push_back(std::shared_ptr<LLEventStream>(new LLEventStream("bob", true)));
}
ensure_equals("last tweaked LLEventStream name", streams.back()->getName(), "bob10");
}
diff --git a/indra/test/namedtempfile.h b/indra/test/namedtempfile.h
index 525a35000d..ad14cebbd1 100644
--- a/indra/test/namedtempfile.h
+++ b/indra/test/namedtempfile.h
@@ -67,14 +67,31 @@ public:
std::string getName() const { return mPath.string(); }
- void peep()
+ template <typename CALLABLE>
+ void peep_via(CALLABLE&& callable) const
{
- std::cout << "File '" << mPath << "' contains:\n";
- boost::filesystem::ifstream reader(mPath);
+ std::forward<CALLABLE>(callable)(stringize("File '", mPath, "' contains:"));
+ boost::filesystem::ifstream reader(mPath, std::ios::binary);
std::string line;
while (std::getline(reader, line))
- std::cout << line << '\n';
- std::cout << "---\n";
+ std::forward<CALLABLE>(callable)(line);
+ std::forward<CALLABLE>(callable)("---");
+ }
+
+ void peep_log() const
+ {
+ peep_via([](const std::string& line){ LL_DEBUGS() << line << LL_ENDL; });
+ }
+
+ void peep(std::ostream& out=std::cout) const
+ {
+ peep_via([&out](const std::string& line){ out << line << '\n'; });
+ }
+
+ friend std::ostream& operator<<(std::ostream& out, const NamedTempFile& self)
+ {
+ self.peep(out);
+ return out;
}
static boost::filesystem::path temp_path(const std::string_view& pfx="",
@@ -103,7 +120,7 @@ protected:
{
// Create file in a temporary place.
mPath = temp_path(pfx, sfx);
- boost::filesystem::ofstream out{ mPath };
+ boost::filesystem::ofstream out{ mPath, std::ios::binary };
// Write desired content.
func(out);
}
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 9dd33c574d..f1c5991330 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -54,6 +54,12 @@
#endif
#ifndef LL_WINDOWS
+
+typedef struct {
+ void *re_pcre;
+ size_t re_nsub;
+ size_t re_erroffset;
+} regex_t;
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#endif
@@ -97,7 +103,7 @@ public:
class RecordToTempFile : public LLError::Recorder, public boost::noncopyable
{
public:
- RecordToTempFile(apr_pool_t* pPool)
+ RecordToTempFile()
: LLError::Recorder(),
boost::noncopyable(),
mTempFile("log", ""),
@@ -141,11 +147,11 @@ private:
class LLReplayLogReal: public LLReplayLog, public boost::noncopyable
{
public:
- LLReplayLogReal(LLError::ELevel level, apr_pool_t* pool)
+ LLReplayLogReal(LLError::ELevel level)
: LLReplayLog(),
boost::noncopyable(),
mOldSettings(LLError::saveAndResetSettings()),
- mRecorder(new RecordToTempFile(pool))
+ mRecorder(new RecordToTempFile())
{
LLError::setFatalFunction(wouldHaveCrashed);
LLError::setDefaultLevel(level);
@@ -160,12 +166,12 @@ public:
virtual void reset()
{
- boost::dynamic_pointer_cast<RecordToTempFile>(mRecorder)->reset();
+ std::dynamic_pointer_cast<RecordToTempFile>(mRecorder)->reset();
}
virtual void replay(std::ostream& out)
{
- boost::dynamic_pointer_cast<RecordToTempFile>(mRecorder)->replay(out);
+ std::dynamic_pointer_cast<RecordToTempFile>(mRecorder)->replay(out);
}
private:
@@ -179,7 +185,7 @@ class LLTestCallback : public chained_callback
public:
LLTestCallback(bool verbose_mode, std::ostream *stream,
- boost::shared_ptr<LLReplayLog> replayer) :
+ std::shared_ptr<LLReplayLog> replayer) :
mVerboseMode(verbose_mode),
mTotalTests(0),
mPassedTests(0),
@@ -187,7 +193,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, [](std::ostream*){})),
+ mStream(std::shared_ptr<std::ostream>(&std::cout, [](std::ostream*){})),
mReplayer(replayer)
{
if (stream)
@@ -201,7 +207,7 @@ public:
// Allocate and assign in two separate steps, per Herb Sutter.
// (Until we turn on C++11 support, have to wrap *stream with
// boost::ref() due to lack of perfect forwarding.)
- boost::shared_ptr<std::ostream> pstream(new TeeStream(std::cout, boost::ref(*stream)));
+ std::shared_ptr<std::ostream> pstream(new TeeStream(std::cout, boost::ref(*stream)));
mStream = pstream;
}
}
@@ -259,7 +265,7 @@ public:
break;
case tut::test_result::ex:
++mFailedTests;
- out << "exception: " << tr.exception_typeid;
+ out << "exception: " << LLError::Log::demangle(tr.exception_typeid.c_str());
break;
case tut::test_result::warn:
++mFailedTests;
@@ -325,8 +331,8 @@ protected:
int mPassedTests;
int mFailedTests;
int mSkippedTests;
- boost::shared_ptr<std::ostream> mStream;
- boost::shared_ptr<LLReplayLog> mReplayer;
+ std::shared_ptr<std::ostream> mStream;
+ std::shared_ptr<LLReplayLog> mReplayer;
};
// TeamCity specific class which emits service messages
@@ -336,7 +342,7 @@ class LLTCTestCallback : public LLTestCallback
{
public:
LLTCTestCallback(bool verbose_mode, std::ostream *stream,
- boost::shared_ptr<LLReplayLog> replayer) :
+ std::shared_ptr<LLReplayLog> replayer) :
LLTestCallback(verbose_mode, stream, replayer)
{
}
@@ -401,7 +407,7 @@ public:
{
// Per http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages
std::string result;
- BOOST_FOREACH(char c, str)
+ for (char c : str)
{
switch (c)
{
@@ -549,7 +555,7 @@ int main(int argc, char **argv)
apr_status_t apr_err;
const char* opt_arg = NULL;
int opt_id = 0;
- boost::scoped_ptr<llofstream> output;
+ std::unique_ptr<llofstream> output;
const char *touch = NULL;
while(true)
@@ -608,7 +614,7 @@ int main(int argc, char **argv)
// set up logging
const char* LOGFAIL = getenv("LOGFAIL");
- boost::shared_ptr<LLReplayLog> replayer{boost::make_shared<LLReplayLog>()};
+ std::shared_ptr<LLReplayLog> replayer{std::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.
@@ -624,7 +630,7 @@ int main(int argc, char **argv)
if (LOGFAIL && *LOGFAIL)
{
LLError::ELevel level = LLError::decodeLevel(LOGFAIL);
- replayer.reset(new LLReplayLogReal(level, gAPRPoolp));
+ replayer.reset(new LLReplayLogReal(level));
}
}
LLError::setFatalFunction(wouldHaveCrashed);