yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
screenshot_assertion.h
Go to the documentation of this file.
1#ifndef YAZE_APP_TEST_SCREENSHOT_ASSERTION_H
2#define YAZE_APP_TEST_SCREENSHOT_ASSERTION_H
3
4#include <chrono>
5#include <cstdint>
6#include <functional>
7#include <string>
8#include <vector>
9
10#include "absl/status/status.h"
11#include "absl/status/statusor.h"
12
13namespace yaze {
14namespace test {
15
20 int x = 0;
21 int y = 0;
22 int width = 0; // 0 = full width
23 int height = 0; // 0 = full height
24
25 bool IsFullScreen() const { return width == 0 && height == 0; }
26
27 static ScreenRegion FullScreen() { return {0, 0, 0, 0}; }
28 static ScreenRegion At(int x, int y, int w, int h) { return {x, y, w, h}; }
29};
30
35 bool passed = false;
36 float similarity = 0.0f; // 0.0 to 1.0 (1.0 = identical)
37 float difference_percentage = 0.0f; // Percentage of pixels that differ
38 int total_pixels = 0;
40
41 // Difference visualization
42 std::string diff_image_path; // Path to generated diff image
43 std::vector<ScreenRegion> differing_regions; // Clusters of differences
44
45 // Performance
46 std::chrono::milliseconds comparison_time{0};
47 std::string error_message;
48};
49
54 float tolerance = 0.95f; // Minimum similarity to pass (0.95 = 95%)
55
56 // Per-pixel tolerance (for anti-aliasing, etc.)
57 int color_threshold = 10; // Max RGB difference per channel (0-255)
58
59 // Ignore regions (for dynamic content like timers)
60 std::vector<ScreenRegion> ignore_regions;
61
62 // Output options
64 std::string diff_output_dir = "/tmp/yaze_test_diffs";
65
66 // Comparison algorithm
67 enum class Algorithm {
68 kPixelExact, // Exact pixel match (with color threshold)
69 kPerceptualHash, // Perceptual hashing (more tolerant)
70 kStructuralSim, // SSIM-like structural comparison
71 };
73};
74
78struct Screenshot {
79 std::vector<uint8_t> data; // RGBA pixel data
80 int width = 0;
81 int height = 0;
82 std::string source; // Path or description of source
83
84 bool IsValid() const {
85 return !data.empty() && width > 0 && height > 0 &&
86 data.size() == static_cast<size_t>(width * height * 4);
87 }
88
89 size_t GetPixelIndex(int x, int y) const {
90 return static_cast<size_t>((y * width + x) * 4);
91 }
92};
93
122 public:
125
126 // Configuration
127 void SetConfig(const ComparisonConfig& config) { config_ = config; }
128 const ComparisonConfig& GetConfig() const { return config_; }
129
130 // Screenshot capture
131 using CaptureCallback = std::function<absl::StatusOr<Screenshot>()>;
133 capture_callback_ = std::move(callback);
134 }
135
136 // --- Core Assertions ---
137
141 absl::StatusOr<ComparisonResult> AssertMatchesReference(
142 const std::string& reference_path);
143
147 absl::StatusOr<ComparisonResult> AssertMatchesScreenshot(
148 const Screenshot& expected);
149
153 absl::StatusOr<ComparisonResult> AssertRegionMatches(
154 const std::string& reference_path, const ScreenRegion& region);
155
159 absl::StatusOr<ComparisonResult> AssertChanged(
160 const std::string& baseline_name);
161
165 absl::StatusOr<ComparisonResult> AssertUnchanged(
166 const std::string& baseline_name);
167
168 // --- Baseline Management ---
169
173 absl::Status CaptureBaseline(const std::string& name);
174
178 absl::Status SaveAsReference(const std::string& path);
179
183 absl::StatusOr<Screenshot> LoadReference(const std::string& path);
184
188 absl::StatusOr<Screenshot> GetBaseline(const std::string& name) const;
189
193 void ClearBaselines() { baselines_.clear(); }
194
195 // --- Comparison Utilities ---
196
200 ComparisonResult Compare(const Screenshot& actual,
201 const Screenshot& expected);
202
207 const Screenshot& expected,
208 const ScreenRegion& region);
209
213 absl::StatusOr<std::string> GenerateDiffImage(const Screenshot& actual,
214 const Screenshot& expected,
215 const std::string& output_path);
216
217 // --- Pixel-Level Assertions ---
218
228 absl::StatusOr<bool> AssertPixelColor(int x, int y, uint8_t r, uint8_t g,
229 uint8_t b, int tolerance = 10);
230
234 absl::StatusOr<bool> AssertRegionContainsColor(
235 const ScreenRegion& region, uint8_t r, uint8_t g, uint8_t b,
236 float min_coverage = 0.1f); // At least 10% of pixels
237
241 absl::StatusOr<bool> AssertRegionExcludesColor(const ScreenRegion& region,
242 uint8_t r, uint8_t g,
243 uint8_t b, int tolerance = 10);
244
245 // --- Convenience Methods ---
246
250 absl::StatusOr<Screenshot> CaptureScreen();
251
255 static absl::Status SaveScreenshot(const Screenshot& screenshot,
256 const std::string& path);
257
261 static absl::StatusOr<Screenshot> LoadScreenshot(const std::string& path);
262
263 private:
266 std::unordered_map<std::string, Screenshot> baselines_;
267
268 // Comparison algorithms
270 const Screenshot& expected,
271 const ScreenRegion& region);
273 const Screenshot& expected);
275 const Screenshot& expected);
276
277 // Helper methods
278 bool ColorsMatch(uint8_t r1, uint8_t g1, uint8_t b1, uint8_t r2, uint8_t g2,
279 uint8_t b2, int threshold) const;
280 std::vector<ScreenRegion> FindDifferingRegions(const Screenshot& actual,
281 const Screenshot& expected,
282 int threshold);
283};
284
285// --- Test Macros ---
286
295#define YAZE_ASSERT_SCREENSHOT_MATCHES(assertion, reference_path) \
296 do { \
297 auto result = (assertion).AssertMatchesReference(reference_path); \
298 ASSERT_TRUE(result.ok()) << result.status().message(); \
299 EXPECT_TRUE(result->passed) \
300 << "Screenshot mismatch: " << result->difference_percentage \
301 << "% different, expected <" \
302 << (1.0f - (assertion).GetConfig().tolerance) * 100 \
303 << "%\nDiff image: " << result->diff_image_path; \
304 } while (0)
305
309#define YAZE_ASSERT_SCREENSHOT_CHANGED(assertion, baseline_name) \
310 do { \
311 auto result = (assertion).AssertChanged(baseline_name); \
312 ASSERT_TRUE(result.ok()) << result.status().message(); \
313 EXPECT_TRUE(result->passed) \
314 << "Expected screenshot to change but similarity was " \
315 << result->similarity * 100 << "%"; \
316 } while (0)
317
321#define YAZE_ASSERT_SCREENSHOT_UNCHANGED(assertion, baseline_name) \
322 do { \
323 auto result = (assertion).AssertUnchanged(baseline_name); \
324 ASSERT_TRUE(result.ok()) << result.status().message(); \
325 EXPECT_TRUE(result->passed) \
326 << "Expected screenshot unchanged but " \
327 << result->difference_percentage << "% different\n" \
328 << "Diff image: " << result->diff_image_path; \
329 } while (0)
330
331} // namespace test
332} // namespace yaze
333
334#endif // YAZE_APP_TEST_SCREENSHOT_ASSERTION_H
Utilities for screenshot-based testing assertions.
absl::StatusOr< ComparisonResult > AssertMatchesReference(const std::string &reference_path)
Assert current screen matches a reference image file.
absl::StatusOr< ComparisonResult > AssertUnchanged(const std::string &baseline_name)
Assert screen has NOT changed since baseline.
static absl::Status SaveScreenshot(const Screenshot &screenshot, const std::string &path)
Save screenshot to file (PNG format).
absl::StatusOr< Screenshot > CaptureScreen()
Capture current screen and return it.
ComparisonResult CompareStructural(const Screenshot &actual, const Screenshot &expected)
std::function< absl::StatusOr< Screenshot >()> CaptureCallback
absl::StatusOr< bool > AssertRegionExcludesColor(const ScreenRegion &region, uint8_t r, uint8_t g, uint8_t b, int tolerance=10)
Assert region does NOT contain a specific color.
absl::StatusOr< Screenshot > LoadReference(const std::string &path)
Load a reference image from file.
void ClearBaselines()
Clear all captured baselines.
void SetConfig(const ComparisonConfig &config)
absl::StatusOr< bool > AssertPixelColor(int x, int y, uint8_t r, uint8_t g, uint8_t b, int tolerance=10)
Assert pixel at (x, y) has expected color.
absl::StatusOr< std::string > GenerateDiffImage(const Screenshot &actual, const Screenshot &expected, const std::string &output_path)
Generate a visual diff image.
absl::StatusOr< ComparisonResult > AssertRegionMatches(const std::string &reference_path, const ScreenRegion &region)
Assert a specific region matches reference.
std::unordered_map< std::string, Screenshot > baselines_
ComparisonResult ComparePixelExact(const Screenshot &actual, const Screenshot &expected, const ScreenRegion &region)
absl::Status CaptureBaseline(const std::string &name)
Capture and store a baseline screenshot.
static absl::StatusOr< Screenshot > LoadScreenshot(const std::string &path)
Load screenshot from file.
bool ColorsMatch(uint8_t r1, uint8_t g1, uint8_t b1, uint8_t r2, uint8_t g2, uint8_t b2, int threshold) const
absl::Status SaveAsReference(const std::string &path)
Save current screen as a new reference image.
ComparisonResult Compare(const Screenshot &actual, const Screenshot &expected)
Compare two screenshots.
absl::StatusOr< Screenshot > GetBaseline(const std::string &name) const
Get a previously captured baseline.
absl::StatusOr< ComparisonResult > AssertChanged(const std::string &baseline_name)
Assert screen has changed since baseline.
ComparisonResult ComparePerceptualHash(const Screenshot &actual, const Screenshot &expected)
std::vector< ScreenRegion > FindDifferingRegions(const Screenshot &actual, const Screenshot &expected, int threshold)
absl::StatusOr< bool > AssertRegionContainsColor(const ScreenRegion &region, uint8_t r, uint8_t g, uint8_t b, float min_coverage=0.1f)
Assert region contains a specific color.
void SetCaptureCallback(CaptureCallback callback)
ComparisonResult CompareRegion(const Screenshot &actual, const Screenshot &expected, const ScreenRegion &region)
Compare specific regions of two screenshots.
absl::StatusOr< ComparisonResult > AssertMatchesScreenshot(const Screenshot &expected)
Assert current screen matches another Screenshot object.
const ComparisonConfig & GetConfig() const
Configuration for screenshot comparison.
std::vector< ScreenRegion > ignore_regions
Result of a screenshot comparison.
std::vector< ScreenRegion > differing_regions
std::chrono::milliseconds comparison_time
Region of interest for screenshot comparison.
static ScreenRegion At(int x, int y, int w, int h)
static ScreenRegion FullScreen()
Screenshot data container.
std::vector< uint8_t > data
size_t GetPixelIndex(int x, int y) const