#[cfg(test)]
use crate::core::material::Material;
use crate::rendering::shader_registry::ShaderType;
use crate::scene::object::{Instance, InstanceData, PhysicsPushConstants};
#[test]
fn shader_type_default_is_pbr() {
assert_eq!(ShaderType::default(), ShaderType::Pbr);
}
#[test]
fn shader_type_sort_keys_are_unique_and_ordered() {
let all = ShaderType::all();
let mut keys: Vec<u32> = all.iter().map(|s| s.sort_key()).collect();
let original = keys.clone();
keys.sort();
keys.dedup();
assert_eq!(keys.len(), all.len());
assert_eq!(keys, original);
}
#[test]
fn shader_type_equality_and_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(ShaderType::Pbr);
set.insert(ShaderType::Unlit);
set.insert(ShaderType::Pbr);
assert_eq!(set.len(), 2);
assert!(set.contains(&ShaderType::Pbr));
assert!(set.contains(&ShaderType::Unlit));
}
#[test]
fn shader_type_is_copy() {
let a = ShaderType::Emissive;
let b = a; assert_eq!(a, b);
}
#[test]
fn material_default_has_pbr_shader() {
let mat = Material::default();
assert_eq!(mat.shader, ShaderType::Pbr);
}
#[test]
fn material_builder_sets_shader() {
let mat = Material::standard().shader(ShaderType::Unlit).build();
assert_eq!(mat.shader, ShaderType::Unlit);
}
#[test]
fn material_builder_default_shader_is_pbr() {
let mat = Material::standard().build();
assert_eq!(mat.shader, ShaderType::Pbr);
}
#[test]
fn material_builder_defaults_match_material_defaults() {
let expected = Material::default();
let actual = Material::standard().build();
assert_eq!(actual.color, expected.color);
assert_eq!(actual.emissive, expected.emissive);
assert_eq!(actual.roughness, expected.roughness);
assert_eq!(actual.metalness, expected.metalness);
assert_eq!(actual.shader, expected.shader);
assert_eq!(actual.base_color_texture, expected.base_color_texture);
assert_eq!(
actual.metallic_roughness_texture,
expected.metallic_roughness_texture
);
}
#[test]
fn material_builder_chaining_preserves_shader() {
let mat = Material::standard()
.color([1.0, 0.0, 0.0])
.roughness(0.8)
.metalness(0.5)
.shader(ShaderType::NormalDebug)
.emissive(0.0)
.build();
assert_eq!(mat.shader, ShaderType::NormalDebug);
assert_eq!(mat.color, [1.0, 0.0, 0.0]);
assert_eq!(mat.roughness, 0.8);
assert_eq!(mat.metalness, 0.5);
}
#[test]
fn material_builder_shader_can_be_overridden() {
let mat = Material::standard()
.shader(ShaderType::Unlit)
.shader(ShaderType::Emissive) .build();
assert_eq!(mat.shader, ShaderType::Emissive);
}
#[test]
fn instance_default_has_pbr_shader() {
let inst = Instance::default();
assert_eq!(inst.shader, ShaderType::Pbr);
}
#[test]
fn instance_custom_shader() {
let inst = Instance {
shader: ShaderType::Unlit,
..Default::default()
};
assert_eq!(inst.shader, ShaderType::Unlit);
}
#[test]
fn instance_clone_preserves_shader() {
let inst = Instance {
shader: ShaderType::Emissive,
color: [1.0, 0.0, 0.0],
..Default::default()
};
let cloned = inst.clone();
assert_eq!(cloned.shader, ShaderType::Emissive);
assert_eq!(cloned.color, [1.0, 0.0, 0.0]);
}
#[test]
fn instance_material_copy_preserves_every_property() {
let material = Material::standard()
.color([0.2, 0.4, 0.6])
.emissive(1.25)
.roughness(0.15)
.metalness(0.85)
.shader(ShaderType::Unlit)
.base_color_texture(3)
.metallic_roughness_texture(7)
.build();
let mut instance = Instance::default();
instance.apply_material(&material);
assert_eq!(instance.color, material.color);
assert_eq!(instance.emissive, material.emissive);
assert_eq!(instance.roughness, material.roughness);
assert_eq!(instance.metalness, material.metalness);
assert_eq!(instance.shader, material.shader);
assert_eq!(instance.base_color_texture, material.base_color_texture);
assert_eq!(
instance.metallic_roughness_texture,
material.metallic_roughness_texture
);
}
#[test]
fn gpu_physics_struct_layout_is_stable() {
use std::mem::{align_of, offset_of, size_of};
assert_eq!(size_of::<InstanceData>(), 144);
assert_eq!(align_of::<InstanceData>(), 4);
assert_eq!(offset_of!(InstanceData, model), 0);
assert_eq!(offset_of!(InstanceData, color), 64);
assert_eq!(offset_of!(InstanceData, mat_props), 80);
assert_eq!(offset_of!(InstanceData, velocity), 96);
assert_eq!(offset_of!(InstanceData, angular_velocity), 112);
assert_eq!(offset_of!(InstanceData, physic_props), 128);
assert_eq!(size_of::<PhysicsPushConstants>(), 48);
assert_eq!(offset_of!(PhysicsPushConstants, global_gravity), 32);
}
#[test]
fn every_compute_shader_uses_the_canonical_instance_layout() {
let shaders = [
include_str!("shaders/compute/basic.comp"),
include_str!("shaders/compute/cs_grid_build.comp"),
include_str!("shaders/compute/cull.comp"),
include_str!("shaders/compute/empty.comp"),
include_str!("shaders/compute/full.comp"),
include_str!("shaders/compute/grid_build.comp"),
include_str!("shaders/compute/mid.comp"),
include_str!("shaders/compute/no_coll.comp"),
include_str!("shaders/compute/physics_simple.glsl"),
];
let fields = [
"mat4 model",
"vec4 color",
"vec4 mat_props",
"vec4 velocity",
"vec4 angular_velocity",
"vec4 physic_props",
];
for shader in shaders {
let mut previous = 0;
for field in fields {
let offset =
shader.find(field).expect("canonical field is missing");
assert!(offset >= previous, "compute shader field order differs");
previous = offset;
}
}
}
#[test]
fn every_physics_push_constant_layout_has_explicit_padding() {
let shaders = [
include_str!("shaders/compute/basic.comp"),
include_str!("shaders/compute/cs_grid_build.comp"),
include_str!("shaders/compute/empty.comp"),
include_str!("shaders/compute/full.comp"),
include_str!("shaders/compute/grid_build.comp"),
include_str!("shaders/compute/mid.comp"),
include_str!("shaders/compute/no_coll.comp"),
include_str!("shaders/compute/physics_simple.glsl"),
];
for shader in shaders {
let padding = shader
.find("_pad[3]")
.expect("push-constant padding is missing");
let gravity = shader
.find("global_gravity")
.expect("global gravity push constant is missing");
assert!(padding < gravity, "padding must precede global_gravity");
}
}
#[test]
fn same_shader_same_key_groups_together() {
let shader_a = ShaderType::Pbr;
let shader_b = ShaderType::Pbr;
assert_eq!(shader_a, shader_b); }
#[test]
fn different_shader_different_key_separates() {
let shader_a = ShaderType::Pbr;
let shader_b = ShaderType::Unlit;
assert_ne!(shader_a, shader_b); }