summaryrefslogtreecommitdiff
path: root/indra/test
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2023-09-08 14:14:09 -0400
committerNat Goodspeed <nat@lindenlab.com>2023-09-08 14:14:09 -0400
commitc7546ea65e55143ff3d2d82d8c289bbac7fffe0f (patch)
treed97d48168d71bc07557feaf44136701d2f3c149d /indra/test
parentd459b3a1ca317c6927dffacda3aac3b580c0dfb1 (diff)
SL-18837: Make llsdserialize_test debug output conditional.
Move hexdump() and hexmix() stream formatters to new hexdump.h for potential use by other tests. In toPythonUsing() helper function, add a temp file to receive Python script debug output, and direct debug output to that file. On test failure, dump the contents of that file to the log. Give NamedTempFile::peep() an optional target std::ostream; refactor implementation as peep_via() that accepts a callable to process each text line. Add operator<<() to stream the contents of a NamedTempFile object to ostream -- but don't use that with LL_DEBUGS(), as it flattens the file contents into a single log line. Instead add peep_log(), which streams each individual text line to LL_DEBUGS().
Diffstat (limited to 'indra/test')
-rw-r--r--indra/test/hexdump.h97
-rw-r--r--indra/test/namedtempfile.h25
2 files changed, 118 insertions, 4 deletions
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/namedtempfile.h b/indra/test/namedtempfile.h
index 3a994ae798..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";
+ 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="",