Files
plotter/tests/harness.hpp
T
Martino FerrariandClaude Opus 4.6 37e414bcc5 feat: grade a sparse window's polyline by slope, so phosphor does not switch off on zoom
Intensity grading was gated on the column reduction, which is gated on a
density whose only job is killing the moire beat. Dwell has nothing to do
with that, so narrowing a window past the threshold turned the whole
phosphor model off and a discontinuity went from a third of a flat top's
ink to all of it in one pixel of zoom.

stage_trace_slopes() grades each segment by its own slope instead, with a
measure that agrees with the dense path at the boundary, and reports
itself as FrameStats::slope_traces -- disjoint from column_traces, so a
host asserting graded_traces == column_traces reads the same as before.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-10-08 16:56:10 +02:00

92 lines
2.8 KiB
C++

// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2026 Martino Ferrari
#pragma once
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <chrono>
#include <algorithm>
#include <functional>
#include <string>
#include <utility>
#include <vector>
#include <plot/core/types.hpp>
using plot::f32;
using plot::f64;
using plot::u32;
using plot::u64;
namespace plottest {
struct Case {
const char* name;
std::function<void()> fn;
};
inline std::vector<Case>& cases() {
static std::vector<Case> c;
return c;
}
struct Reg {
Reg(const char* n, std::function<void()> f) { cases().push_back({n, std::move(f)}); }
};
struct Failure {
std::string msg;
};
/// Compares two doubles within `eps`. `PLOT_CHECK_NEAR(a, b)` leaves it to the
/// default below; pass an explicit tolerance for computed values.
inline constexpr double kNearEps = 1e-9;
inline void check_near(double a, double b, double eps, const char* file, int line,
const char* lhs, const char* rhs) {
if (!(std::fabs(a - b) <= eps)) {
throw Failure{std::string(file) + ":" + std::to_string(line) + " CHECK_NEAR(" + lhs + ", " +
rhs + ") got " + std::to_string(a) + " vs " + std::to_string(b)};
}
}
inline void check_near(double a, double b, const char* file, int line, const char* lhs,
const char* rhs) {
check_near(a, b, kNearEps, file, line, lhs, rhs);
}
inline int run_all() {
int failed = 0;
const char* only = std::getenv("PLOT_TEST_FILTER");
for (auto& c : cases()) {
if (only != nullptr && std::string(c.name).find(only) == std::string::npos) continue;
try {
c.fn();
std::printf("[ ok ] %s\n", c.name);
} catch (const Failure& f) {
std::printf("[FAIL] %s: %s\n", c.name, f.msg.c_str());
++failed;
}
}
std::printf("%zu cases, %d failed\n", cases().size(), failed);
return failed == 0 ? 0 : 1;
}
} // namespace plottest
#define PLOT_TEST(name) \
static void name(); \
static ::plottest::Reg reg_##name(#name, name); \
static void name()
#define PLOT_CHECK(cond) \
do { \
if (!(cond)) \
throw ::plottest::Failure{std::string(__FILE__) + ":" + std::to_string(__LINE__) + \
" CHECK(" #cond ")"}; \
} while (0)
#define PLOT_CHECK_NEAR(a, b, ...) \
::plottest::check_near((a), (b) __VA_OPT__(,) __VA_ARGS__, __FILE__, __LINE__, #a, #b)