singularity-rs/tests/preset_test.rs
xfy 3bf1f1ac83 feat(ui): add preset module with hash-based Custom detection
Preset::Cinematic/Performance/Web write 5 params (steps, render_scale,
bloom/disk/aa quality); Custom is a no-op marker. params_hash hashes
ONLY preset-touched fields so non-preset edits (disk_tilt, etc.) don't
spuriously flip the bar to Custom. Test-pinned via tests/preset_test.rs.

Exports ui + params from lib.rs so the test can construct params.

Lib-compile unblock: the library crate could not build with only
`pub mod {params,physics,ui}` because src/ui/mod.rs's ui_system
references crate::camera and crate::scene (transitively crate::render).
Added pub mod {camera,scene,render,web} to lib.rs and reworked main.rs
to consume them via `use singularity_rs::*` instead of redeclaring
the same file-level modules. preset is declared `pub mod` (not private
`mod`) because tests/preset_test.rs imports it cross-crate.
2026-07-17 15:27:18 +08:00

42 lines
1.6 KiB
Rust

use singularity_rs::params::BlackHoleParams;
use singularity_rs::ui::preset::{Preset, apply, canonical_hash, params_hash};
#[test]
fn canonical_hash_matches_just_applied_params() {
// After applying a preset, params_hash of the result must equal that
// preset's canonical_hash — otherwise the Custom-detection logic would
// immediately flip a freshly-applied preset back to Custom.
let mut p = BlackHoleParams::default();
for preset in [Preset::Cinematic, Preset::Performance, Preset::Web] {
apply(preset, &mut p);
assert_eq!(
canonical_hash(preset),
params_hash(&p),
"preset {:?}: apply() did not reproduce canonical_hash",
preset
);
}
}
#[test]
fn non_preset_field_change_flips_to_custom() {
// Editing a field that NO preset touches (disk_tilt is not in any preset bundle)
// must NOT change params_hash. This guards the "hash only preset fields"
// invariant: non-preset edits must not spuriously flip to Custom.
let mut p = BlackHoleParams::default();
let h0 = params_hash(&p);
p.disk_tilt = 1.0; // not in any preset bundle
assert_eq!(h0, params_hash(&p), "non-preset field leaked into hash");
}
#[test]
fn preset_field_change_differs_from_canonical() {
// Editing a preset-touched field after applying must change the hash
// away from the preset's canonical_hash (i.e. flip to Custom).
let mut p = BlackHoleParams::default();
apply(Preset::Cinematic, &mut p);
let h_canonical = canonical_hash(Preset::Cinematic);
p.steps = 299; // off by one from the Cinematic bundle
assert_ne!(h_canonical, params_hash(&p));
}