| … | 137 unchanged lines hidden |
| 138 |
138 |
|
skip_reason = nil, |
| 139 |
139 |
|
profile = path.join(dir, "profile.json"), |
| 140 |
140 |
|
capture = path.join(dir, "capture.png"), |
|
141 |
+ |
readback = path.join(dir, "readback.ppm"), |
|
142 |
+ |
assertion_spec = path.join(dir, "assertions.json"), |
| 141 |
143 |
|
analysis = path.join(dir, "analysis.json"), |
| 142 |
144 |
|
raw_result = path.join(dir, "run.json"), |
| 143 |
145 |
|
assertions = scene.assertions, |
| … | 39 unchanged lines hidden |
| 183 |
185 |
|
return row |
| 184 |
186 |
|
end |
| 185 |
187 |
|
|
| 186 |
|
- |
row.status = "fail" |
| 187 |
|
- |
row.error = "trusted GPU readback proof artifact missing" |
|
188 |
+ |
if not path.exists(row.readback) then |
|
189 |
+ |
row.status = "fail" |
|
190 |
+ |
row.error = "trusted GPU readback proof artifact missing" |
|
191 |
+ |
return row |
|
192 |
+ |
end |
|
193 |
+ |
|
|
194 |
+ |
local spec = { |
|
195 |
+ |
source_kind = "readback", |
|
196 |
+ |
width = scene.width or 256, |
|
197 |
+ |
height = scene.height or 256, |
|
198 |
+ |
origin = "top-left", |
|
199 |
+ |
assertions = scene.assertions, |
|
200 |
+ |
} |
|
201 |
+ |
path.write_file(row.assertion_spec, json.encode(spec)) |
|
202 |
+ |
local assert_cmd = table.concat({ |
|
203 |
+ |
"python3", |
|
204 |
+ |
path.shell_quote(path.join(root, "tools", "visual_assert.py")), |
|
205 |
+ |
path.shell_quote(row.readback), |
|
206 |
+ |
"--spec", path.shell_quote(row.assertion_spec), |
|
207 |
+ |
"--json", path.shell_quote(row.analysis), |
|
208 |
+ |
}, " ") |
|
209 |
+ |
local assert_status = process.run(process.with_cwd(root, assert_cmd)) |
|
210 |
+ |
if assert_status ~= 0 then |
|
211 |
+ |
row.status = "fail" |
|
212 |
+ |
row.error = "visual assertions failed" |
|
213 |
+ |
row.exit_code = assert_status |
|
214 |
+ |
return row |
|
215 |
+ |
end |
|
216 |
+ |
row.status = "pass" |
|
217 |
+ |
row.error = nil |
| 188 |
218 |
|
return row |
| 189 |
219 |
|
end |
| 190 |
220 |
|
|
| … | 120 unchanged lines hidden |