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
132 std::function<absl::StatusOr<Screenshot>()>;
134 capture_callback_ = std::move(callback);
135 }
136
137 // --- Core Assertions ---
138
142 absl::StatusOr<ComparisonResult> AssertMatchesReference(
143 const std::string& reference_path);
144
148 absl::StatusOr<ComparisonResult> AssertMatchesScreenshot(
149 const Screenshot& expected);
150
154 absl::StatusOr<ComparisonResult> AssertRegionMatches(
155 const std::string& reference_path,
156 const ScreenRegion& region);
157
161 absl::StatusOr<ComparisonResult> AssertChanged(
162 const std::string& baseline_name);
163
167 absl::StatusOr<ComparisonResult> AssertUnchanged(
168 const std::string& baseline_name);
169
170 // --- Baseline Management ---
171
175 absl::Status CaptureBaseline(const std::string& name);
176
180 absl::Status SaveAsReference(const std::string& path);
181
185 absl::StatusOr<Screenshot> LoadReference(const std::string& path);
186
190 absl::StatusOr<Screenshot> GetBaseline(const std::string& name) const;
191
195 void ClearBaselines() { baselines_.clear(); }
196
197 // --- Comparison Utilities ---
198
202 ComparisonResult Compare(const Screenshot& actual,
203 const Screenshot& expected);
204
209 const Screenshot& expected,
210 const ScreenRegion& region);
211
215 absl::StatusOr<std::string> GenerateDiffImage(
216 const Screenshot& actual,
217 const Screenshot& expected,
218 const std::string& output_path);
219
220 // --- Pixel-Level Assertions ---
221
231 absl::StatusOr<bool> AssertPixelColor(
232 int x, int y, uint8_t r, uint8_t g, uint8_t b, int tolerance = 10);
233
237 absl::StatusOr<bool> AssertRegionContainsColor(
238 const ScreenRegion& region,
239 uint8_t r, uint8_t g, uint8_t b,
240 float min_coverage = 0.1f); // At least 10% of pixels
241
245 absl::StatusOr<bool> AssertRegionExcludesColor(
246 const ScreenRegion& region,
247 uint8_t r, uint8_t g, uint8_t b,
248 int tolerance = 10);
249
250 // --- Convenience Methods ---
251
255 absl::StatusOr<Screenshot> CaptureScreen();
256
260 static absl::Status SaveScreenshot(const Screenshot& screenshot,
261 const std::string& path);
262
266 static absl::StatusOr<Screenshot> LoadScreenshot(const std::string& path);
267
268 private:
271 std::unordered_map<std::string, Screenshot> baselines_;
272
273 // Comparison algorithms
275 const Screenshot& expected,
276 const ScreenRegion& region);
278 const Screenshot& expected);
280 const Screenshot& expected);
281
282 // Helper methods
283 bool ColorsMatch(uint8_t r1, uint8_t g1, uint8_t b1,
284 uint8_t r2, uint8_t g2, uint8_t b2,
285 int threshold) const;
286 std::vector<ScreenRegion> FindDifferingRegions(
287 const Screenshot& actual,
288 const Screenshot& expected,
289 int threshold);
290};
291
292// --- Test Macros ---
293
302#define YAZE_ASSERT_SCREENSHOT_MATCHES(assertion, reference_path) \
303 do { \
304 auto result = (assertion).AssertMatchesReference(reference_path); \
305 ASSERT_TRUE(result.ok()) << result.status().message(); \
306 EXPECT_TRUE(result->passed) \
307 << "Screenshot mismatch: " << result->difference_percentage \
308 << "% different, expected <" << (1.0f - (assertion).GetConfig().tolerance) * 100 \
309 << "%\nDiff image: " << result->diff_image_path; \
310 } while (0)
311
315#define YAZE_ASSERT_SCREENSHOT_CHANGED(assertion, baseline_name) \
316 do { \
317 auto result = (assertion).AssertChanged(baseline_name); \
318 ASSERT_TRUE(result.ok()) << result.status().message(); \
319 EXPECT_TRUE(result->passed) \
320 << "Expected screenshot to change but similarity was " \
321 << result->similarity * 100 << "%"; \
322 } while (0)
323
327#define YAZE_ASSERT_SCREENSHOT_UNCHANGED(assertion, baseline_name) \
328 do { \
329 auto result = (assertion).AssertUnchanged(baseline_name); \
330 ASSERT_TRUE(result.ok()) << result.status().message(); \
331 EXPECT_TRUE(result->passed) \
332 << "Expected screenshot unchanged but " \
333 << result->difference_percentage << "% different\n" \
334 << "Diff image: " << result->diff_image_path; \
335 } while (0)
336
337} // namespace test
338} // namespace yaze
339
340#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)
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_
std::function< absl::StatusOr< Screenshot >()> CaptureCallback
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