Skip to content

Commit c696cc6

Browse files
committed
pixelbender: Add assembly integration tests
1 parent 2cfab42 commit c696cc6

File tree

30 files changed

+582
-0
lines changed

30 files changed

+582
-0
lines changed

Cargo.lock

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ members = [
2020
"render/canvas",
2121
"render/naga-agal",
2222
"render/pixel_bender",
23+
"render/pixel_bender/assembly_tests",
2324
"render/wgpu",
2425
"render/webgl",
2526

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[package]
2+
name = "pixel_bender_assembly_tests"
3+
authors.workspace = true
4+
edition.workspace = true
5+
homepage.workspace = true
6+
license.workspace = true
7+
repository.workspace = true
8+
version.workspace = true
9+
10+
[lints]
11+
workspace = true
12+
13+
[dev-dependencies]
14+
pixel_bender = { path = "..", features = ["assembly"]}
15+
ruffle_fs_tests_runner = { path = "../../../tests/fs-tests-runner" }
16+
libtest-mimic = { workspace = true }
17+
serde = { workspace = true, features = ["derive"] }
18+
toml = { workspace = true }
19+
anyhow = { workspace = true }
20+
clap = { workspace = true }
21+
vfs = { workspace = true }
22+
23+
[[test]]
24+
name = "assembly_tests"
25+
harness = false
26+
path = "src/runner.rs"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# pbasm Integration Tests
2+
3+
This directory contains integration tests for `pbasm`.
4+
Each directory with `test.toml` contains one integration test.
5+
6+
## `test.toml`
7+
8+
```toml
9+
# Type of the test, either 'assembly', 'disassembly', or 'roundtrip'.
10+
type = "roundtrip"
11+
# If set to true, the test will be ignored.
12+
ignore = false
13+
```
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
//! Pixel Bender assembly tests runner.
2+
3+
use anyhow::{anyhow, Context, Result};
4+
use libtest_mimic::Trial;
5+
use pixel_bender::assembly::PixelBenderShaderAssembly;
6+
use pixel_bender::disassembly::PixelBenderShaderDisassembly;
7+
use pixel_bender::parse_shader;
8+
use ruffle_fs_tests_runner::{FsTestsRunner, TestLoaderParams};
9+
use serde::Deserialize;
10+
use std::fs::File;
11+
use std::io::Write;
12+
use std::path::Path;
13+
use std::{borrow::Cow, path::PathBuf};
14+
use vfs::VfsPath;
15+
16+
const TEST_TOML_NAME: &str = "test.toml";
17+
18+
#[derive(Clone, Copy, Deserialize)]
19+
enum TestType {
20+
Roundtrip,
21+
Assemble,
22+
Dissassemble,
23+
}
24+
25+
impl TestType {
26+
fn performs_assembly(self) -> bool {
27+
matches!(self, TestType::Assemble | TestType::Roundtrip)
28+
}
29+
30+
fn performs_disassembly(self) -> bool {
31+
matches!(self, TestType::Dissassemble | TestType::Roundtrip)
32+
}
33+
}
34+
35+
#[derive(Clone, Deserialize)]
36+
#[serde(default, deny_unknown_fields)]
37+
struct TestOptions {
38+
pub r#type: TestType,
39+
pub ignore: bool,
40+
pub pbj_path: String,
41+
pub asm_path: String,
42+
}
43+
44+
impl Default for TestOptions {
45+
fn default() -> Self {
46+
Self {
47+
r#type: TestType::Roundtrip,
48+
ignore: false,
49+
pbj_path: "test.pbj".to_owned(),
50+
asm_path: "test.pbasm".to_owned(),
51+
}
52+
}
53+
}
54+
55+
impl TestOptions {
56+
fn read(path: &VfsPath) -> Result<Self> {
57+
let result = toml::from_str(&path.read_to_string()?)?;
58+
Ok(result)
59+
}
60+
61+
fn pbj_path(&self, test_dir: &VfsPath) -> Result<VfsPath> {
62+
test_dir
63+
.join(&self.pbj_path)
64+
.context("Failed to get pbj path")
65+
}
66+
67+
fn asm_path(&self, test_dir: &VfsPath) -> Result<VfsPath> {
68+
test_dir
69+
.join(&self.asm_path)
70+
.context("Failed to get asm path")
71+
}
72+
}
73+
74+
fn main() {
75+
let mut runner = FsTestsRunner::new();
76+
77+
runner
78+
.with_descriptor_name(Cow::Borrowed(TEST_TOML_NAME))
79+
.with_test_loader(Box::new(|params| Some(load_test(params))));
80+
81+
runner.run()
82+
}
83+
84+
fn load_test(params: TestLoaderParams) -> Trial {
85+
let test_dir = params.test_dir.clone();
86+
let test_dir_real = params.test_dir_real.into_owned();
87+
let name = params.test_name;
88+
89+
let descriptor_path = test_dir.join("test.toml").unwrap();
90+
91+
let options = TestOptions::read(&descriptor_path)
92+
.map_err(|e| anyhow!("Failed to parse {}: {e}", descriptor_path.as_str()))
93+
.expect("Failed to parse test descriptor");
94+
let ignore = options.ignore;
95+
96+
let mut trial = Trial::test(name.to_string(), move || {
97+
let pbj_path = options.pbj_path(&test_dir)?;
98+
let pbj_path_real = to_real_path(&test_dir_real, &pbj_path);
99+
let asm_path = options.asm_path(&test_dir)?;
100+
let asm_path_real = to_real_path(&test_dir_real, &asm_path);
101+
102+
let pbj_actual_path = test_dir_real.join("actual.pbj");
103+
let asm_actual_path = test_dir_real.join("actual.pbasm");
104+
105+
if options.r#type.performs_assembly() {
106+
let source = asm_path_real.to_str().unwrap().to_string();
107+
let output = pbj_actual_path.to_str().unwrap().to_string();
108+
109+
run_test(&pbj_path_real, &pbj_actual_path, move || {
110+
let input =
111+
std::fs::read_to_string(&source).context("Failed to open source file")?;
112+
let mut write =
113+
File::create(output).map_err(|e| anyhow!("Failed to create file: {e}"))?;
114+
let assembly = PixelBenderShaderAssembly::new(&input, &mut write);
115+
assembly.assemble()?;
116+
Ok(())
117+
})?;
118+
}
119+
120+
if options.r#type.performs_disassembly() {
121+
let source = pbj_path_real.to_str().unwrap().to_string();
122+
let output = asm_actual_path.to_str().unwrap().to_string();
123+
124+
run_test(&asm_path_real, &asm_actual_path, move || {
125+
let data = std::fs::read(&source).context("Failed to open source file")?;
126+
let parsed = parse_shader(&data, false)
127+
.map_err(|e| anyhow!("Failed to parse the shader: {e}"))?;
128+
let mut write =
129+
File::create(output).map_err(|e| anyhow!("Failed to create file: {e}"))?;
130+
write!(write, "{}", PixelBenderShaderDisassembly(&parsed))
131+
.context("Failed to write disassembly")?;
132+
Ok(())
133+
})?;
134+
}
135+
136+
Ok(())
137+
});
138+
if ignore {
139+
trial = trial.with_ignored_flag(true);
140+
}
141+
trial
142+
}
143+
144+
fn to_real_path(real_dir: &Path, file: &VfsPath) -> PathBuf {
145+
real_dir.join(file.as_str().strip_prefix('/').unwrap())
146+
}
147+
148+
fn run_test<F>(expected_path: &Path, actual_path: &Path, proc: F) -> Result<()>
149+
where
150+
F: FnOnce() -> Result<()>,
151+
{
152+
proc().map_err(|e: anyhow::Error| anyhow!("Failed to execute (dis)assembly: {e}"))?;
153+
154+
let actual = std::fs::read(actual_path)?;
155+
let expected = std::fs::read(expected_path).map_err(|e| {
156+
anyhow!(
157+
"Error reading test file {}: {e}",
158+
expected_path.to_string_lossy()
159+
)
160+
})?;
161+
162+
if actual != expected {
163+
return Err(anyhow!(
164+
"Test failed: Output doesn't match: {}",
165+
actual_path.to_string_lossy()
166+
));
167+
}
168+
169+
let _ = std::fs::remove_file(actual_path);
170+
Ok(())
171+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
actual.pbj
2+
actual.pbasm
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
version 1i
2+
name "Test"
3+
4+
mov i1.rgba, i0.rgba
5+
mov i1.rgb, i0.rgb
6+
mov i1.rga, i0.rgb
7+
mov i1.rba, i0.rgb
8+
mov i1.gba, i0.rgb
9+
mov i1.rg, i0.rg
10+
mov i1.rb, i0.rg
11+
mov i1.ra, i0.rg
12+
mov i1.gb, i0.rg
13+
mov i1.ga, i0.rg
14+
mov i1.ba, i0.rg
15+
mov i1.r, i0.r
16+
mov i1.g, i0.r
17+
mov i1.b, i0.r
18+
mov i1.a, i0.r
19+
mov i1.rgb, i0.rgba
20+
mov i1.rgb, i0.rg
21+
mov i1.rgb, i0.r
22+
mov i1.rg, i0.rgba
23+
mov i1.rg, i0.rgb
24+
mov i1.rg, i0.r
25+
mov i1.r, i0.rgba
26+
mov i1.r, i0.rgb
27+
mov i1.r, i0.rg
204 Bytes
Binary file not shown.

render/pixel_bender/assembly_tests/tests/dst_channels/test.toml

Whitespace-only changes.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
version 1i
2+
name "Test"
3+
4+
param.in "param1", float2x2, f1.m2
5+
6+
param.in "param2", float3x3, f1.m3
7+
8+
param.in "param2", float4x4, f1.m4
9+
10+
mov f1.m2, f0.m2
11+
mov f1.m3, f0.m3
12+
mov f1.m4, f0.m4
13+
mov f1.rgba, f0.m2
14+
mov f1.rgb, f0.m2
15+
mov f1.rba, f0.m2
16+
mov f1.rga, f0.m2
17+
mov f1.rgb, f0.m2
18+
mov f1.rg, f0.m2
19+
mov f1.rb, f0.m2
20+
mov f1.ra, f0.m2
21+
mov f1.gb, f0.m2
22+
mov f1.ga, f0.m2
23+
mov f1.ba, f0.m2
24+
mov f1.r, f0.m2
25+
mov f1.g, f0.m2
26+
mov f1.b, f0.m2
27+
mov f1.a, f0.m2
28+
mov f1.rgba, f0.m3
29+
mov f1.rgb, f0.m3
30+
mov f1.rba, f0.m3
31+
mov f1.rga, f0.m3
32+
mov f1.rgb, f0.m3
33+
mov f1.rg, f0.m3
34+
mov f1.rb, f0.m3
35+
mov f1.ra, f0.m3
36+
mov f1.gb, f0.m3
37+
mov f1.ga, f0.m3
38+
mov f1.ba, f0.m3
39+
mov f1.r, f0.m3
40+
mov f1.g, f0.m3
41+
mov f1.b, f0.m3
42+
mov f1.a, f0.m3
43+
mov f1.rgba, f0.m4
44+
mov f1.rgb, f0.m4
45+
mov f1.rba, f0.m4
46+
mov f1.rga, f0.m4
47+
mov f1.rgb, f0.m4
48+
mov f1.rg, f0.m4
49+
mov f1.rb, f0.m4
50+
mov f1.ra, f0.m4
51+
mov f1.gb, f0.m4
52+
mov f1.ga, f0.m4
53+
mov f1.ba, f0.m4
54+
mov f1.r, f0.m4
55+
mov f1.g, f0.m4
56+
mov f1.b, f0.m4
57+
mov f1.a, f0.m4

0 commit comments

Comments
 (0)