From fc8428952b0f1b490ae8147aa7e315ec6f4525ff Mon Sep 17 00:00:00 2001 From: "Matt C. Jackson" Date: Tue, 13 Dec 2022 21:10:44 +0000 Subject: [PATCH 1/6] Converted the exception to an error message refs: #5530 --- hoot-core/src/main/cpp/hoot/core/util/Settings.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp b/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp index 24443ceb74..7f72585a75 100644 --- a/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp +++ b/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp @@ -636,7 +636,10 @@ void Settings::parseCommonArguments(QStringList& args, const QStringList toIgnor LOG_VART(optionVal); if (!conf().hasKey(optionName)) - throw IllegalArgumentException("Unknown settings option: (" + optionName + ")"); + { + LOG_ERROR("Skipping unknown settings option: (" + optionName + ")"); + continue; + } const QStringList values = optionVal.split(";", QString::SkipEmptyParts); LOG_VART(values); From 3671fca76d0d49c3c571c3378286a7cddced2f01 Mon Sep 17 00:00:00 2001 From: "Matt C. Jackson" Date: Wed, 14 Dec 2022 21:51:05 +0000 Subject: [PATCH 2/6] Converted a JSON settings file exception to an error. refs: #5530 --- hoot-core/src/main/cpp/hoot/core/util/Settings.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp b/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp index 7f72585a75..9d40e17b72 100644 --- a/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp +++ b/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp @@ -142,7 +142,10 @@ class JsonLoader // Throw an exception for unrecognized keys if (!_s->hasKey(optionName)) - throw IllegalArgumentException("Unknown JSON setting: (" + optionName + ")"); + { + LOG_ERROR("Skipping unknown JSON setting: (" + optionName + ")"); + continue; + } // Set key/value pair as name and data, data() turns everything to a string const QString optionVal = QString::fromUtf8(element.second.data().c_str()); From 108fc83dffba80189829f21be91f5fe707286014 Mon Sep 17 00:00:00 2001 From: Ben Marchant <13385275+bmarchant@users.noreply.github.com> Date: Fri, 13 Jan 2023 10:05:38 -0600 Subject: [PATCH 3/6] Fix infinite loop when bad option is encountered --- hoot-core/src/main/cpp/hoot/core/util/Settings.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp b/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp index 9d40e17b72..c55eb7183c 100644 --- a/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp +++ b/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp @@ -143,7 +143,7 @@ class JsonLoader // Throw an exception for unrecognized keys if (!_s->hasKey(optionName)) { - LOG_ERROR("Skipping unknown JSON setting: (" + optionName + ")"); + LOG_ERROR("Skipping unknown JSON setting: (" << optionName << ")"); continue; } @@ -640,7 +640,9 @@ void Settings::parseCommonArguments(QStringList& args, const QStringList toIgnor if (!conf().hasKey(optionName)) { - LOG_ERROR("Skipping unknown settings option: (" + optionName + ")"); + LOG_ERROR("Skipping unknown settings option: (" << optionName << ")"); + // move on to the next argument + args = args.mid(2); continue; } From 70b1727e6e026dd6336de08f178bc960ea4407a4 Mon Sep 17 00:00:00 2001 From: Ben Marchant <13385275+bmarchant@users.noreply.github.com> Date: Fri, 13 Jan 2023 10:50:11 -0600 Subject: [PATCH 4/6] Copyright :shakes-fist: --- hoot-core/src/main/cpp/hoot/core/util/Settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp b/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp index c55eb7183c..8b73e81cee 100644 --- a/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp +++ b/hoot-core/src/main/cpp/hoot/core/util/Settings.cpp @@ -22,7 +22,7 @@ * This will properly maintain the copyright information. Maxar * copyrights will be updated automatically. * - * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Maxar (http://www.maxar.com/) + * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Maxar (http://www.maxar.com/) */ #include "Settings.h" From a9267b429083d258c6b19f953dc0e39fcecc946b Mon Sep 17 00:00:00 2001 From: Ben Marchant <13385275+bmarchant@users.noreply.github.com> Date: Fri, 13 Jan 2023 14:36:47 -0600 Subject: [PATCH 5/6] Capture the log output to a string if desired, compare that in the Settings unit tests. --- .../test/cpp/hoot/core/util/SettingsTest.cpp | 13 +++---- hoot-core/src/main/cpp/hoot/core/util/Log.cpp | 38 +++++++++++++------ hoot-core/src/main/cpp/hoot/core/util/Log.h | 36 ++++++++++++++++++ 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/hoot-core-test/src/test/cpp/hoot/core/util/SettingsTest.cpp b/hoot-core-test/src/test/cpp/hoot/core/util/SettingsTest.cpp index 0d51d40ce9..b77f7d0de2 100644 --- a/hoot-core-test/src/test/cpp/hoot/core/util/SettingsTest.cpp +++ b/hoot-core-test/src/test/cpp/hoot/core/util/SettingsTest.cpp @@ -146,19 +146,18 @@ class SettingsTest : public HootTestFixture void invalidOptionNameTest() { + QString log; QStringList args; args.append("-D"); args.append("blah=true"); - QString exceptionMsg; - try + // Capture the log output in a nested scope { + CaptureLog capture; Settings::parseCommonArguments(args); + log = capture.getLogsStripped(); } - catch (const HootException& e) - { - exceptionMsg = e.what(); - } - HOOT_STR_EQUALS("Unknown settings option: (blah)", exceptionMsg); + // Compare the captured log output + HOOT_STR_EQUALS("Skipping unknown settings option: (blah)", log); } void invalidOperatorsTest() diff --git a/hoot-core/src/main/cpp/hoot/core/util/Log.cpp b/hoot-core/src/main/cpp/hoot/core/util/Log.cpp index ec3a08b2de..89f77232ba 100644 --- a/hoot-core/src/main/cpp/hoot/core/util/Log.cpp +++ b/hoot-core/src/main/cpp/hoot/core/util/Log.cpp @@ -116,12 +116,13 @@ void Log::log(WarningLevel level, const string& str, const string& filename, QDateTime dt = QDateTime::currentDateTime(); // takes the form: "09:34:21.635 WARN () " - cout << beginDecoration(level) - << dt.toString("hh:mm:ss.zzz") << " " << setw(6) << left << Log::levelToString(level) - << " " << ellipsisStr(filename) << "(" << setw(4) << right << lineNumber << ")" << " " - << str - << endDecoration() - << endl; + std::ostream& s = *_stream; + s << beginDecoration(level) + << dt.toString("hh:mm:ss.zzz") << " " << setw(6) << left << Log::levelToString(level) + << " " << ellipsisStr(filename) << "(" << setw(4) << right << lineNumber << ")" << " " + << str + << endDecoration() + << endl; } } @@ -133,12 +134,13 @@ void Log::progress(WarningLevel level, const string& str, const string& filename QDateTime dt = QDateTime::currentDateTime(); // takes the form: "09:34:21.635 WARN () " - cout << beginDecoration(level) - << dt.toString("hh:mm:ss.zzz") << " " << setw(6) << left << Log::levelToString(level) - << " " << ellipsisStr(filename) << "(" << setw(4) << right << lineNumber << ")" << " " - << str << " \r" - << endDecoration() - << flush; + std::ostream& s = *_stream; + s << beginDecoration(level) + << dt.toString("hh:mm:ss.zzz") << " " << setw(6) << left << Log::levelToString(level) + << " " << ellipsisStr(filename) << "(" << setw(4) << right << lineNumber << ")" << " " + << str << " \r" + << endDecoration() + << flush; } } @@ -295,4 +297,16 @@ const char* Log::endDecoration() const return ""; } +QString CaptureLog::getLogsStripped() const +{ + static QRegularExpression regex(".*?\\( *\\d+\\) (.*)", QRegularExpression::OptimizeOnFirstUsageOption); + + QString logs = getLogs(); + QStringList matches; + auto match_it = regex.globalMatch(logs); + while (match_it.hasNext()) + matches << match_it.next().captured(1); + return matches.join("\n"); +} + } diff --git a/hoot-core/src/main/cpp/hoot/core/util/Log.h b/hoot-core/src/main/cpp/hoot/core/util/Log.h index 5430e1c940..5caef27ea8 100644 --- a/hoot-core/src/main/cpp/hoot/core/util/Log.h +++ b/hoot-core/src/main/cpp/hoot/core/util/Log.h @@ -36,6 +36,7 @@ // Standard #include +#include #include #include #include @@ -128,6 +129,9 @@ class Log void setDecorateLogs(bool decorate) { _decorateLogs = decorate; } + std::ostream* getStream() const { return _stream; } + void setStream(std::ostream* stream) { _stream = stream; } + private: WarningLevel _level; @@ -136,6 +140,9 @@ class Log QStringList _excludeClassFilter; bool _decorateLogs; + /** By default all logging goes to std::cout */ + std::ostream* _stream = &std::cout; + Log(); /** Default destructor */ ~Log() = default; @@ -189,6 +196,35 @@ class DisableLog Log::WarningLevel _oldLevel; }; +class CaptureLog +{ +public: + CaptureLog(Log::WarningLevel level = Log::Error) + { + Log& log = Log::getInstance(); + _stream = log.getStream(); + _level = log.getLevel(); + log.setLevel(level); + log.setStream(&_strstream); + } + + ~CaptureLog() + { + Log& log = Log::getInstance(); + log.setLevel(_level); + log.setStream(_stream); + } + + QString getLogs() const { return QString(_strstream.str().c_str()); } + QString getLogsStripped() const; + +private: + + Log::WarningLevel _level; + std::ostream* _stream; + std::stringstream _strstream; +}; + // recreate the TGS stream utils within our namespace. I haven't found an elegant way to reliably // use operator<< within the Tgs namespace from within hoot. :( #include From 927c8f6e1c9776d5817d26297a741e213efdc7a2 Mon Sep 17 00:00:00 2001 From: Ben Marchant <13385275+bmarchant@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:20:25 -0600 Subject: [PATCH 6/6] Copyright --- hoot-core-test/src/test/cpp/hoot/core/util/SettingsTest.cpp | 2 +- hoot-core/src/main/cpp/hoot/core/util/Log.cpp | 2 +- hoot-core/src/main/cpp/hoot/core/util/Log.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hoot-core-test/src/test/cpp/hoot/core/util/SettingsTest.cpp b/hoot-core-test/src/test/cpp/hoot/core/util/SettingsTest.cpp index b77f7d0de2..acf5b2182f 100644 --- a/hoot-core-test/src/test/cpp/hoot/core/util/SettingsTest.cpp +++ b/hoot-core-test/src/test/cpp/hoot/core/util/SettingsTest.cpp @@ -22,7 +22,7 @@ * This will properly maintain the copyright information. Maxar * copyrights will be updated automatically. * - * @copyright Copyright (C) 2012, 2013, 2015, 2016, 2018, 2019, 2020, 2021, 2022 Maxar (http://www.maxar.com/) + * @copyright Copyright (C) 2012, 2013, 2015, 2016, 2018, 2019, 2020, 2021, 2022, 2023 Maxar (http://www.maxar.com/) */ // Hoot diff --git a/hoot-core/src/main/cpp/hoot/core/util/Log.cpp b/hoot-core/src/main/cpp/hoot/core/util/Log.cpp index 89f77232ba..da55a2d672 100644 --- a/hoot-core/src/main/cpp/hoot/core/util/Log.cpp +++ b/hoot-core/src/main/cpp/hoot/core/util/Log.cpp @@ -22,7 +22,7 @@ * This will properly maintain the copyright information. Maxar * copyrights will be updated automatically. * - * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Maxar (http://www.maxar.com/) + * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Maxar (http://www.maxar.com/) */ #include "Log.h" diff --git a/hoot-core/src/main/cpp/hoot/core/util/Log.h b/hoot-core/src/main/cpp/hoot/core/util/Log.h index 5caef27ea8..6fc95528cb 100644 --- a/hoot-core/src/main/cpp/hoot/core/util/Log.h +++ b/hoot-core/src/main/cpp/hoot/core/util/Log.h @@ -22,7 +22,7 @@ * This will properly maintain the copyright information. Maxar * copyrights will be updated automatically. * - * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Maxar (http://www.maxar.com/) + * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Maxar (http://www.maxar.com/) */ #ifndef LOG_H