feat(libmeanfield): centrifugal + pressure
This commit is contained in:
@@ -1,127 +1,496 @@
|
||||
#include <algorithm>
|
||||
#include <catch2/catch_session.hpp>
|
||||
#include <catch2/reporters/catch_reporter_streaming_base.hpp>
|
||||
#include <catch2/reporters/catch_reporter_registrars.hpp>
|
||||
#include <catch2/catch_test_case_info.hpp>
|
||||
#include <catch2/reporters/catch_reporter_registrars.hpp>
|
||||
#include <catch2/reporters/catch_reporter_streaming_base.hpp>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <mfem.hpp>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <fourdst/config/config.h>
|
||||
#include <CLI/CLI.hpp>
|
||||
#include <fourdst/config/config.h>
|
||||
|
||||
import mean_field;
|
||||
import test_helpers;
|
||||
|
||||
std::string escapeHtml(const std::string &data) {
|
||||
std::string buffer;
|
||||
buffer.reserve(data.size());
|
||||
for (size_t pos = 0; pos != data.size(); ++pos) {
|
||||
switch (data[pos]) {
|
||||
case '&':
|
||||
buffer.append("&");
|
||||
break;
|
||||
case '\"':
|
||||
buffer.append(""");
|
||||
break;
|
||||
case '\'':
|
||||
buffer.append("'");
|
||||
break;
|
||||
case '<':
|
||||
buffer.append("<");
|
||||
break;
|
||||
case '>':
|
||||
buffer.append(">");
|
||||
break;
|
||||
default:
|
||||
buffer.append(&data[pos], 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::string ansiToHtml(const std::string &text) {
|
||||
// Convert text to HTML-safe first
|
||||
std::string htmlEscaped = escapeHtml(text);
|
||||
|
||||
std::ostringstream oss;
|
||||
size_t i = 0;
|
||||
size_t len = htmlEscaped.length();
|
||||
int openSpans = 0;
|
||||
|
||||
auto closeSpans = [&oss, &openSpans]() {
|
||||
while (openSpans > 0) {
|
||||
oss << "</span>";
|
||||
--openSpans;
|
||||
}
|
||||
};
|
||||
|
||||
while (i < len) {
|
||||
// Look for ANSI CSI sequence '\033[' or '\x1b['
|
||||
if ((htmlEscaped[i] == '\033' || htmlEscaped[i] == '\x1b') &&
|
||||
i + 1 < len && htmlEscaped[i + 1] == '[') {
|
||||
size_t seqStart = i + 2;
|
||||
size_t seqEnd = htmlEscaped.find('m', seqStart);
|
||||
|
||||
if (seqEnd != std::string::npos) {
|
||||
std::string codeStr =
|
||||
htmlEscaped.substr(seqStart, seqEnd - seqStart);
|
||||
i = seqEnd + 1;
|
||||
|
||||
std::istringstream codeStream(codeStr);
|
||||
std::string codeVal;
|
||||
|
||||
// Defaults if sequence is just \033[m (Reset)
|
||||
if (codeStr.empty()) {
|
||||
closeSpans();
|
||||
continue;
|
||||
}
|
||||
|
||||
while (std::getline(codeStream, codeVal, ';')) {
|
||||
int code = 0;
|
||||
try {
|
||||
code = std::stoi(codeVal);
|
||||
} catch (...) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case 0: // Reset
|
||||
closeSpans();
|
||||
break;
|
||||
case 1: // Bold
|
||||
oss << "<span style='font-weight:bold;'>";
|
||||
openSpans++;
|
||||
break;
|
||||
case 2: // Dim
|
||||
oss << "<span style='opacity:0.7;'>";
|
||||
openSpans++;
|
||||
break;
|
||||
// Standard Foreground Colors
|
||||
case 30:
|
||||
oss << "<span style='color:#2c3e50;'>";
|
||||
openSpans++;
|
||||
break; // Black
|
||||
case 31:
|
||||
oss << "<span style='color:#e74c3c;'>";
|
||||
openSpans++;
|
||||
break; // Red
|
||||
case 32:
|
||||
oss << "<span style='color:#27ae60;'>";
|
||||
openSpans++;
|
||||
break; // Green
|
||||
case 33:
|
||||
oss << "<span style='color:#f39c12;'>";
|
||||
openSpans++;
|
||||
break; // Yellow
|
||||
case 34:
|
||||
oss << "<span style='color:#2980b9;'>";
|
||||
openSpans++;
|
||||
break; // Blue
|
||||
case 35:
|
||||
oss << "<span style='color:#8e44ad;'>";
|
||||
openSpans++;
|
||||
break; // Magenta
|
||||
case 36:
|
||||
oss << "<span style='color:#16a085;'>";
|
||||
openSpans++;
|
||||
break; // Cyan
|
||||
case 37:
|
||||
oss << "<span style='color:#bdc3c7;'>";
|
||||
openSpans++;
|
||||
break; // Light Gray
|
||||
// Bright Foreground Colors
|
||||
case 90:
|
||||
oss << "<span style='color:#7f8c8d;'>";
|
||||
openSpans++;
|
||||
break; // Dark Gray
|
||||
case 91:
|
||||
oss << "<span style='color:#ff6b6b;'>";
|
||||
openSpans++;
|
||||
break; // Bright Red
|
||||
case 92:
|
||||
oss << "<span style='color:#51cf66;'>";
|
||||
openSpans++;
|
||||
break; // Bright Green
|
||||
case 93:
|
||||
oss << "<span style='color:#fcc419;'>";
|
||||
openSpans++;
|
||||
break; // Bright Yellow
|
||||
case 94:
|
||||
oss << "<span style='color:#339af0;'>";
|
||||
openSpans++;
|
||||
break; // Bright Blue
|
||||
case 95:
|
||||
oss << "<span style='color:#cc5de8;'>";
|
||||
openSpans++;
|
||||
break; // Bright Magenta
|
||||
case 96:
|
||||
oss << "<span style='color:#22b8cf;'>";
|
||||
openSpans++;
|
||||
break; // Bright Cyan
|
||||
case 97:
|
||||
oss << "<span style='color:#ffffff;'>";
|
||||
openSpans++;
|
||||
break; // White
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
oss << htmlEscaped[i];
|
||||
++i;
|
||||
}
|
||||
|
||||
closeSpans();
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::vector<std::string> wrapText(
|
||||
const std::string &text,
|
||||
size_t width
|
||||
) {
|
||||
std::vector<std::string> lines;
|
||||
std::istringstream words(text);
|
||||
std::string word, line;
|
||||
|
||||
while (words >> word) {
|
||||
if (line.length() + word.length() + 1 > width) {
|
||||
if (!line.empty()) {
|
||||
lines.push_back(line);
|
||||
line.clear();
|
||||
}
|
||||
if (word.length() > width) {
|
||||
lines.push_back(word.substr(0, width - 3) + "...");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!line.empty())
|
||||
line += " ";
|
||||
line += word;
|
||||
}
|
||||
if (!line.empty())
|
||||
lines.push_back(line);
|
||||
if (lines.empty())
|
||||
lines.push_back("");
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
class CheckReporter : public Catch::StreamingReporterBase {
|
||||
// Accumulate failure messages for the current test case
|
||||
struct TestCaseData {
|
||||
std::string name;
|
||||
std::string tags;
|
||||
bool passed;
|
||||
std::size_t assertionsPassed;
|
||||
std::size_t assertionsFailed;
|
||||
std::vector<std::string> failureMessages;
|
||||
std::vector<std::string> infoMessages;
|
||||
};
|
||||
|
||||
std::vector<std::string> m_currentFailures;
|
||||
std::vector<std::string> m_currentInfos;
|
||||
std::vector<TestCaseData> m_testRunData;
|
||||
|
||||
public:
|
||||
using StreamingReporterBase::StreamingReporterBase;
|
||||
|
||||
static std::string getDescription() {
|
||||
return "Fixed-width table reporter with detailed assertion failures.";
|
||||
return "Console reporter with wrapping, tags, and collapsible HTML "
|
||||
"export "
|
||||
"with ANSI color rendering.";
|
||||
}
|
||||
|
||||
void testRunStarting(Catch::TestRunInfo const& _testRunInfo) override {
|
||||
void testRunStarting(Catch::TestRunInfo const &_testRunInfo) override {
|
||||
StreamingReporterBase::testRunStarting(_testRunInfo);
|
||||
|
||||
std::cout << '\n';
|
||||
std::cout << std::left << std::setw(55) << "Test Case Name"
|
||||
<< "Status "
|
||||
<< std::right << std::setw(8) << "Passed"
|
||||
std::cout << std::left << std::setw(85) << "Test Case Name"
|
||||
<< "Status " << std::right << std::setw(8) << "Passed"
|
||||
<< std::setw(8) << "Failed" << '\n';
|
||||
std::cout << std::string(81, '-') << '\n';
|
||||
std::cout << std::string(121, '-') << '\n';
|
||||
}
|
||||
|
||||
// 1. Hook into every assertion to catch failures
|
||||
void assertionEnded(Catch::AssertionStats const& assertionStats) override {
|
||||
void assertionEnded(Catch::AssertionStats const &assertionStats) override {
|
||||
StreamingReporterBase::assertionEnded(assertionStats);
|
||||
|
||||
// If the assertion failed, build a detailed message
|
||||
// Capture INFO messages regardless of pass/fail status
|
||||
for (auto const &msg : assertionStats.infoMessages) {
|
||||
m_currentInfos.push_back(msg.message);
|
||||
}
|
||||
|
||||
if (!assertionStats.assertionResult.isOk()) {
|
||||
auto const& result = assertionStats.assertionResult;
|
||||
auto const &result = assertionStats.assertionResult;
|
||||
std::ostringstream oss;
|
||||
|
||||
// Format: -> FAILED: [file:line]
|
||||
oss << " \033[31m-> FAILED:\033[0m "
|
||||
<< result.getSourceInfo().file << ":" << result.getSourceInfo().line << '\n';
|
||||
<< result.getSourceInfo().file << ":"
|
||||
<< result.getSourceInfo().line << '\n';
|
||||
oss << " " << result.getTestMacroName() << "( "
|
||||
<< result.getExpression() << " )\n";
|
||||
|
||||
// Print the macro used (e.g., REQUIRE, CHECK) and the expression
|
||||
oss << " " << result.getTestMacroName() << "( " << result.getExpression() << " )\n";
|
||||
|
||||
// Print what it actually evaluated to (e.g., 1 == 2)
|
||||
if (result.hasExpandedExpression()) {
|
||||
oss << " with expansion:\n"
|
||||
<< " " << result.getExpandedExpression() << '\n';
|
||||
}
|
||||
|
||||
// Capture any INFO() messages attached to this assertion
|
||||
for (auto const& msg : assertionStats.infoMessages) {
|
||||
oss << " info: " << msg.message << '\n';
|
||||
for (auto const &msg : assertionStats.infoMessages) {
|
||||
oss << " \033[36m[INFO]\033[0m " << msg.message << '\n';
|
||||
}
|
||||
|
||||
m_currentFailures.push_back(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void testCaseEnded(Catch::TestCaseStats const& stats) override {
|
||||
void testCaseEnded(Catch::TestCaseStats const &stats) override {
|
||||
StreamingReporterBase::testCaseEnded(stats);
|
||||
|
||||
bool passed = stats.totals.assertions.allPassed();
|
||||
bool passed = stats.totals.assertions.allPassed();
|
||||
std::string mark = passed ? "\033[32m✓\033[0m" : "\033[31m✗\033[0m";
|
||||
|
||||
std::string name = stats.testInfo->name;
|
||||
if (name.length() > 53) {
|
||||
name = name.substr(0, 50) + "...";
|
||||
auto wrappedName = wrapText(name, 83);
|
||||
|
||||
std::cout << std::left << std::setw(85) << wrappedName[0] << mark
|
||||
<< " " << std::right << std::setw(8)
|
||||
<< stats.totals.assertions.passed << std::setw(8)
|
||||
<< stats.totals.assertions.failed << '\n';
|
||||
|
||||
for (size_t i = 1; i < wrappedName.size(); ++i) {
|
||||
std::cout << " \033[90m↳ \033[0m" // Dim indent arrow
|
||||
<< std::left << std::setw(81) << wrappedName[i] << '\n';
|
||||
}
|
||||
|
||||
// Print the table row
|
||||
std::cout << std::left << std::setw(55) << name
|
||||
<< mark << " "
|
||||
<< std::right << std::setw(8) << stats.totals.assertions.passed
|
||||
<< std::setw(8) << stats.totals.assertions.failed << '\n';
|
||||
std::string tagsStr = stats.testInfo->tagsAsString();
|
||||
if (!tagsStr.empty()) {
|
||||
auto wrappedTags = wrapText("Tags: " + tagsStr, 83);
|
||||
for (const auto &line : wrappedTags) {
|
||||
std::cout << " \033[36m" << line << "\033[0m\n"; // Cyan
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Print all accumulated failures under the row
|
||||
if (!m_currentFailures.empty()) {
|
||||
std::cout << '\n';
|
||||
for (auto const& failure : m_currentFailures) {
|
||||
for (auto const &failure : m_currentFailures) {
|
||||
std::cout << failure << '\n';
|
||||
}
|
||||
// Add a separator so multiple failing tests don't blur together
|
||||
std::cout << std::string(81, '-') << '\n';
|
||||
|
||||
// Clear the buffer for the next test case
|
||||
m_currentFailures.clear();
|
||||
std::cout << std::string(121, '-') << '\n';
|
||||
}
|
||||
|
||||
m_testRunData.push_back(
|
||||
{name, tagsStr, passed, stats.totals.assertions.passed,
|
||||
stats.totals.assertions.failed, m_currentFailures, m_currentInfos}
|
||||
);
|
||||
|
||||
m_currentFailures.clear();
|
||||
m_currentInfos.clear();
|
||||
}
|
||||
|
||||
void testRunEnded(Catch::TestRunStats const& _testRunStats) override {
|
||||
void testRunEnded(Catch::TestRunStats const &_testRunStats) override {
|
||||
StreamingReporterBase::testRunEnded(_testRunStats);
|
||||
|
||||
std::cout << std::string(81, '=') << '\n';
|
||||
std::cout << std::string(121, '=') << '\n';
|
||||
|
||||
auto const& tc = _testRunStats.totals.testCases;
|
||||
auto const& as = _testRunStats.totals.assertions;
|
||||
auto const &tc = _testRunStats.totals.testCases;
|
||||
auto const &as = _testRunStats.totals.assertions;
|
||||
|
||||
std::string tc_passed_str = tc.passed > 0 ? "\033[32m" + std::to_string(tc.passed) + " passed\033[0m" : "0 passed";
|
||||
std::string tc_failed_str = tc.failed > 0 ? "\033[31m" + std::to_string(tc.failed) + " failed\033[0m" : "0 failed";
|
||||
std::string tc_passed_str =
|
||||
tc.passed > 0
|
||||
? "\033[32m" + std::to_string(tc.passed) + " passed\033[0m"
|
||||
: "0 passed";
|
||||
std::string tc_failed_str =
|
||||
tc.failed > 0
|
||||
? "\033[31m" + std::to_string(tc.failed) + " failed\033[0m"
|
||||
: "0 failed";
|
||||
|
||||
std::string as_passed_str = as.passed > 0 ? "\033[32m" + std::to_string(as.passed) + " passed\033[0m" : "0 passed";
|
||||
std::string as_failed_str = as.failed > 0 ? "\033[31m" + std::to_string(as.failed) + " failed\033[0m" : "0 failed";
|
||||
std::string as_passed_str =
|
||||
as.passed > 0
|
||||
? "\033[32m" + std::to_string(as.passed) + " passed\033[0m"
|
||||
: "0 passed";
|
||||
std::string as_failed_str =
|
||||
as.failed > 0
|
||||
? "\033[31m" + std::to_string(as.failed) + " failed\033[0m"
|
||||
: "0 failed";
|
||||
|
||||
std::cout << "Test Cases: " << tc_passed_str << ", " << tc_failed_str << ", " << tc.total() << " total\n";
|
||||
std::cout << "Assertions: " << as_passed_str << ", " << as_failed_str << ", " << as.total() << " total\n\n";
|
||||
std::cout << "Test Cases: " << tc_passed_str << ", " << tc_failed_str
|
||||
<< ", " << tc.total() << " total\n";
|
||||
std::cout << "Assertions: " << as_passed_str << ", " << as_failed_str
|
||||
<< ", " << as.total() << " total\n\n";
|
||||
|
||||
generateHtmlReport(_testRunStats);
|
||||
}
|
||||
|
||||
private:
|
||||
void generateHtmlReport(Catch::TestRunStats const &stats) {
|
||||
std::ofstream html("test_summary.html");
|
||||
if (!html)
|
||||
return;
|
||||
|
||||
html
|
||||
<< "<!DOCTYPE html>\n<html lang='en'>\n<head>\n"
|
||||
<< "<meta charset='UTF-8'>\n"
|
||||
<< "<meta name='viewport' content='width=device-width, "
|
||||
"initial-scale=1.0'>\n"
|
||||
<< "<title>Test Run Summary</title>\n"
|
||||
<< "<style>\n"
|
||||
<< "body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe "
|
||||
"UI', "
|
||||
"Roboto, Helvetica, Arial, sans-serif; "
|
||||
"background: #f4f6f8; color: #333; margin: 0; padding: 2rem; }\n"
|
||||
<< "h1 { color: #2c3e50; border-bottom: 2px solid #e0e0e0; "
|
||||
"padding-bottom: 0.5rem; }\n"
|
||||
<< ".summary-cards { display: flex; gap: 1rem; margin-bottom: "
|
||||
"2rem; }\n"
|
||||
<< ".card { background: white; padding: 1rem 1.5rem; "
|
||||
"border-radius: "
|
||||
"8px; box-shadow: 0 2px 4px "
|
||||
"rgba(0,0,0,0.05); flex: 1; }\n"
|
||||
<< ".card h3 { margin-top: 0; font-size: 0.9rem; color: #7f8c8d; "
|
||||
"text-transform: uppercase; }\n"
|
||||
<< ".card p { font-size: 1.5rem; font-weight: bold; margin: 0; }\n"
|
||||
<< ".text-green { color: #27ae60; }\n"
|
||||
<< ".text-red { color: #e74c3c; }\n"
|
||||
<< ".test-item { background: white; border-radius: 8px; padding: "
|
||||
"1rem; "
|
||||
"margin-bottom: 1rem; box-shadow: 0 2px "
|
||||
"4px rgba(0,0,0,0.05); border-left: 5px solid #bdc3c7; }\n"
|
||||
<< ".test-item.passed { border-left-color: #27ae60; }\n"
|
||||
<< ".test-item.failed { border-left-color: #e74c3c; }\n"
|
||||
<< ".test-header { display: flex; justify-content: space-between; "
|
||||
"align-items: flex-start; }\n"
|
||||
<< ".test-name { font-size: 1.1rem; font-weight: 600; margin: 0 0 "
|
||||
"0.5rem 0; word-break: break-word; }\n"
|
||||
<< ".tags { font-size: 0.8rem; color: #2980b9; background: "
|
||||
"#ebf5fb; "
|
||||
"padding: 2px 6px; border-radius: 4px; "
|
||||
"display: inline-block; margin-top: 4px; }\n"
|
||||
<< ".stats { font-size: 0.9rem; color: #7f8c8d; }\n"
|
||||
<< "details { margin-top: 0.8rem; background: #f8f9fa; border: 1px "
|
||||
"solid #e9ecef; border-radius: 6px; "
|
||||
"padding: 0.5rem 0.8rem; }\n"
|
||||
<< "summary { cursor: pointer; font-weight: 600; color: #34495e; "
|
||||
"user-select: none; font-size: 0.9rem; }\n"
|
||||
<< "summary:hover { color: #2980b9; }\n"
|
||||
<< "pre { background: #1e293b; color: #f8fafc; padding: 1rem; "
|
||||
"border-radius: 4px; overflow-x: auto; "
|
||||
"font-size: 0.85rem; line-height: 1.4; margin-top: 0.5rem; }\n"
|
||||
<< "pre.info-block { background: #0f172a; border-left: 4px solid "
|
||||
"#0284c7; }\n"
|
||||
<< "</style>\n</head>\n<body>\n";
|
||||
|
||||
html << "<h1>Test Run Summary</h1>\n";
|
||||
|
||||
// Summary Cards
|
||||
html << "<div class='summary-cards'>\n";
|
||||
html << "<div class='card'><h3>Total Cases</h3><p>"
|
||||
<< stats.totals.testCases.total() << "</p></div>\n";
|
||||
html << "<div class='card'><h3>Cases Passed</h3><p class='text-green'>"
|
||||
<< stats.totals.testCases.passed << "</p></div>\n";
|
||||
html << "<div class='card'><h3>Cases Failed</h3><p class='text-red'>"
|
||||
<< stats.totals.testCases.failed << "</p></div>\n";
|
||||
html << "</div>\n";
|
||||
|
||||
for (const auto &test : m_testRunData) {
|
||||
std::string statusClass = test.passed ? "passed" : "failed";
|
||||
html << "<div class='test-item " << statusClass << "'>\n";
|
||||
html << " <div class='test-header'>\n";
|
||||
html << " <div>\n";
|
||||
html << " <h3 class='test-name'>" << escapeHtml(test.name)
|
||||
<< "</h3>\n";
|
||||
if (!test.tags.empty()) {
|
||||
html << " <div class='tags'>" << escapeHtml(test.tags)
|
||||
<< "</div>\n";
|
||||
}
|
||||
html << " </div>\n";
|
||||
html << " <div class='stats'>\n";
|
||||
html << " <span class='text-green'>✓ "
|
||||
<< test.assertionsPassed << "</span> | ";
|
||||
html << " <span class='text-red'>✗ "
|
||||
<< test.assertionsFailed << "</span>\n";
|
||||
html << " </div>\n";
|
||||
html << " </div>\n";
|
||||
|
||||
// Collapsible INFO Messages section with ANSI color rendering
|
||||
if (!test.infoMessages.empty()) {
|
||||
html << " <details>\n";
|
||||
html << " <summary>Info Logs (" << test.infoMessages.size()
|
||||
<< ")</summary>\n";
|
||||
html << " <pre class='info-block'>";
|
||||
for (const auto &info : test.infoMessages) {
|
||||
html << "[INFO] " << ansiToHtml(info) << "\n";
|
||||
}
|
||||
html << "</pre>\n";
|
||||
html << " </details>\n";
|
||||
}
|
||||
|
||||
// Collapsible Failures section with ANSI color rendering
|
||||
if (!test.failureMessages.empty()) {
|
||||
html << " <details open>\n";
|
||||
html << " <summary class='text-red'>Failure Details ("
|
||||
<< test.failureMessages.size() << ")</summary>\n";
|
||||
html << " <pre>";
|
||||
for (const auto &msg : test.failureMessages) {
|
||||
html << ansiToHtml(msg) << "\n";
|
||||
}
|
||||
html << " </pre>\n";
|
||||
html << " </details>\n";
|
||||
}
|
||||
|
||||
html << "</div>\n";
|
||||
}
|
||||
|
||||
html << "</body>\n</html>\n";
|
||||
}
|
||||
};
|
||||
CATCH_REGISTER_REPORTER("check", CheckReporter)
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
CATCH_REGISTER_REPORTER(
|
||||
"check",
|
||||
CheckReporter
|
||||
)
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char *argv[]
|
||||
) {
|
||||
fourdst::config::Config<mean_field::utils::Args> cfg;
|
||||
CLI::App app{"Mean Field Tests"};
|
||||
|
||||
@@ -148,49 +517,56 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<const char*> config_argv;
|
||||
std::vector<const char *> config_argv;
|
||||
config_argv.reserve(config_arguments.size());
|
||||
|
||||
for (const std::string& argument : config_arguments) {
|
||||
for (const std::string &argument : config_arguments) {
|
||||
config_argv.push_back(argument.c_str());
|
||||
}
|
||||
|
||||
try {
|
||||
app.parse(static_cast<int>(config_argv.size()), config_argv.data());
|
||||
} catch (const CLI::ParseError& error) {
|
||||
} catch (const CLI::ParseError &error) {
|
||||
return app.exit(error);
|
||||
}
|
||||
|
||||
std::vector<std::string> catch_arguments;
|
||||
catch_arguments.emplace_back(argv[0]);
|
||||
|
||||
for (const std::string& argument : app.remaining()) {
|
||||
for (const std::string &argument : app.remaining()) {
|
||||
catch_arguments.push_back(argument);
|
||||
}
|
||||
|
||||
for (const std::string& argument : forced_catch_arguments) {
|
||||
for (const std::string &argument : forced_catch_arguments) {
|
||||
catch_arguments.push_back(argument);
|
||||
}
|
||||
|
||||
const auto is_reporter_option = [](const std::string& argument) {
|
||||
return argument == "-r" || argument == "--reporter" || argument.starts_with("-r=") || argument.starts_with("--reporter=");
|
||||
const auto is_reporter_option = [](const std::string &argument) {
|
||||
return argument == "-r" || argument == "--reporter" ||
|
||||
argument.starts_with("-r=") ||
|
||||
argument.starts_with("--reporter=");
|
||||
};
|
||||
|
||||
if (const bool has_reporter = std::ranges::any_of(catch_arguments, is_reporter_option); !has_reporter) {
|
||||
if (const bool has_reporter =
|
||||
std::ranges::any_of(catch_arguments, is_reporter_option);
|
||||
!has_reporter) {
|
||||
catch_arguments.emplace_back("--reporter");
|
||||
catch_arguments.emplace_back("check");
|
||||
}
|
||||
|
||||
std::vector<const char*> catch_argv;
|
||||
std::vector<const char *> catch_argv;
|
||||
catch_argv.reserve(catch_arguments.size());
|
||||
|
||||
for (const std::string& argument : catch_arguments) {
|
||||
for (const std::string &argument : catch_arguments) {
|
||||
catch_argv.push_back(argument.c_str());
|
||||
}
|
||||
|
||||
Catch::Session session;
|
||||
|
||||
if (const int catch_parse_result = session.applyCommandLine(static_cast<int>(catch_argv.size()), catch_argv.data()); catch_parse_result != 0) {
|
||||
if (const int catch_parse_result = session.applyCommandLine(
|
||||
static_cast<int>(catch_argv.size()), catch_argv.data()
|
||||
);
|
||||
catch_parse_result != 0) {
|
||||
return catch_parse_result;
|
||||
}
|
||||
|
||||
@@ -201,7 +577,8 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
const int hdiv_max_q1d = mfem::DeviceDofQuadLimits::Get().HDIV_MAX_Q1D;
|
||||
std::cout << "H(div) maximum Q1D = " << hdiv_max_q1d << '\n';
|
||||
std::cout << "Approximate maximum safe integration order = " << 2 * hdiv_max_q1d - 1 << '\n';
|
||||
std::cout << "Approximate maximum safe integration order = "
|
||||
<< 2 * hdiv_max_q1d - 1 << '\n';
|
||||
|
||||
mean_field::utils::Args test_args = cfg.main();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user