use agent::orbs::{
ModeKey, OrbSize, OrbState,
engine::{MAX_ICON_D, MAX_MORPH_DOTS, MAX_NODE_N, ModeOpts, draw_mode, sanitize_mode_opts},
resolve_preset,
};
#[test]
fn all_states_emit_geometry() {
for &state in OrbState::ALL_STATES {
for &size in OrbSize::ALL_SIZES {
let resolved = resolve_preset(state, size);
let frame = draw_mode(resolved.mode, size.pixels(), 1.25, &resolved.opts);
assert!(
!frame.dots.is_empty(),
"{:?}/{:?} produced zero dots",
state,
size
);
for d in &frame.dots {
assert!(d.r.is_finite() && d.r >= 0.0);
assert!(d.x.is_finite() && d.y.is_finite() && d.z.is_finite());
assert!(d.a >= 0.0 && d.a <= 1.0 + 1e-3);
}
}
}
}
#[test]
fn connecting_emits_lines() {
let resolved = resolve_preset(OrbState::Connecting, OrbSize::Avatar);
let frame = draw_mode(resolved.mode, 64.0, 2.0, &resolved.opts);
assert!(!frame.lines.is_empty(), "connecting should wire edges");
assert!(!frame.dots.is_empty());
}
#[test]
fn reduced_motion_frame_is_deterministic() {
let resolved = resolve_preset(OrbState::Working, OrbSize::Avatar);
let a = draw_mode(resolved.mode, 64.0, 0.6, &resolved.opts);
let b = draw_mode(resolved.mode, 64.0, 0.6, &resolved.opts);
assert_eq!(a.dots.len(), b.dots.len());
for (da, db) in a.dots.iter().zip(b.dots.iter()) {
assert!((da.x - db.x).abs() < 1e-4);
assert!((da.y - db.y).abs() < 1e-4);
}
}
#[test]
fn solve_cycle_survives_float_boundary_move_counts() {
const SLOT_DUR: f32 = 0.58;
let resolved = resolve_preset(OrbState::Solving, OrbSize::Avatar);
for count in 1..40u32 {
let mut opts = resolved.opts.clone();
opts.move_count = Some(count as f32);
for c in 1..=count {
let boundary = 2.0 * c as f32 * SLOT_DUR;
for t in [
f32::from_bits(boundary.to_bits() - 1),
boundary,
f32::from_bits(boundary.to_bits() + 1),
] {
let frame = draw_mode(resolved.mode, 64.0, t, &opts);
assert!(!frame.dots.is_empty());
}
}
}
}
#[test]
fn new_concepts_are_distinct_low_density_modes() {
let concepts = [
(OrbState::Focusing, ModeKey::Focus, 77, 23),
(OrbState::Reasoning, ModeKey::Gyroscope, 90, 32),
(OrbState::Recalling, ModeKey::Echo, 75, 21),
];
for (state, mode, avatar_dots, inline_dots) in concepts {
assert_eq!(ModeKey::from_state(state), mode);
assert!(OrbState::ALL_STATES.contains(&state));
for (size, expected) in [
(OrbSize::Avatar, avatar_dots),
(OrbSize::Inline, inline_dots),
] {
let resolved = resolve_preset(state, size);
let frame = draw_mode(resolved.mode, size.pixels(), 0.6, &resolved.opts);
assert_eq!(frame.dots.len(), expected, "{state:?}/{size:?}");
assert!(
frame.lines.is_empty(),
"new concepts stay on the dot-only paint path"
);
assert!(
frame.dots.len() < 100,
"new concepts must remain low density"
);
}
}
}
#[test]
fn new_concepts_animate_and_keep_their_depth_identity() {
for &state in &[OrbState::Focusing, OrbState::Reasoning, OrbState::Recalling] {
let resolved = resolve_preset(state, OrbSize::Avatar);
let a = draw_mode(resolved.mode, 64.0, 0.2, &resolved.opts);
let b = draw_mode(resolved.mode, 64.0, 1.2, &resolved.opts);
assert!(
a.dots
.iter()
.zip(&b.dots)
.any(|(a, b)| (a.x - b.x).abs() > 0.01 || (a.y - b.y).abs() > 0.01),
"{state:?} did not animate"
);
let has_depth = a.dots.iter().any(|dot| dot.z.abs() > 0.01);
assert_eq!(has_depth, state == OrbState::Reasoning);
}
}
#[test]
fn larger_sizes_add_detail_without_changing_the_legacy_presets() {
assert_eq!(OrbSize::ALL_SIZES.len(), 4);
assert_eq!(OrbSize::Large.pixels(), 96.0);
assert_eq!(OrbSize::Hero.pixels(), 128.0);
for &state in OrbState::ALL_STATES {
let avatar = resolve_preset(state, OrbSize::Avatar);
let large = resolve_preset(state, OrbSize::Large);
let hero = resolve_preset(state, OrbSize::Hero);
let avatar_frame = draw_mode(avatar.mode, 64.0, 0.6, &avatar.opts);
let large_frame = draw_mode(large.mode, 96.0, 0.6, &large.opts);
let hero_frame = draw_mode(hero.mode, 128.0, 0.6, &hero.opts);
assert_eq!(avatar.mode, large.mode);
assert_eq!(avatar.mode, hero.mode);
assert!(
large_frame.dots.len() >= avatar_frame.dots.len(),
"{state:?}/large"
);
assert!(
hero_frame.dots.len() >= large_frame.dots.len(),
"{state:?}/hero"
);
assert!(large.speed <= avatar.speed);
assert!(hero.speed <= large.speed);
}
}
#[test]
fn legacy_all_constant_keeps_its_original_array_shape() {
#[allow(deprecated)]
let original_nine: [OrbState; 9] = OrbState::ALL;
assert_eq!(original_nine.len(), 9);
assert_eq!(OrbState::ALL_STATES.len(), 12);
}
#[test]
fn bench_geometry_cost() {
use std::time::Instant;
for &state in OrbState::ALL_STATES {
for &size in OrbSize::ALL_SIZES {
let resolved = resolve_preset(state, size);
for i in 0..20 {
let _ = draw_mode(
resolved.mode,
size.pixels(),
i as f32 * 0.016,
&resolved.opts,
);
}
let n = 1000usize;
let t0 = Instant::now();
let mut total_dots = 0usize;
let mut total_lines = 0usize;
for i in 0..n {
let f = draw_mode(
resolved.mode,
size.pixels(),
i as f32 * 0.016,
&resolved.opts,
);
total_dots += f.dots.len();
total_lines += f.lines.len();
}
let elapsed = t0.elapsed();
let per = elapsed / n as u32;
let avg_dots = total_dots / n;
let avg_lines = total_lines / n;
eprintln!(
"{:>12}/{:<6} {:>5} dots {:>4} lines {:>8.2?} /frame (~{:.0}k geom-fps)",
state.as_str(),
size.pixels() as u32,
avg_dots,
avg_lines,
per,
1.0 / per.as_secs_f64() / 1000.0
);
}
}
}
#[test]
fn stroke_colours_are_paintable() {
let resolved = resolve_preset(OrbState::Connecting, OrbSize::Avatar);
let mut seen = 0usize;
for i in 0..400 {
let frame = draw_mode(resolved.mode, 64.0, i as f32 * 0.05, &resolved.opts);
for l in &frame.lines {
assert!(
l.a.is_finite() && (0.0..=1.0).contains(&l.a),
"alpha {}",
l.a
);
assert!(
l.white.is_finite() && (0.0..=1.0).contains(&l.white),
"white {}",
l.white
);
assert!(l.w.is_finite() && l.w > 0.0, "stroke width {}", l.w);
assert!(l.x1.is_finite() && l.y1.is_finite());
assert!(l.x2.is_finite() && l.y2.is_finite());
seen += 1;
}
}
assert!(seen > 0, "connecting emitted no strokes across 400 frames");
}
#[test]
fn adversarial_mode_opts_stay_bounded_and_finite() {
let cases: &[(ModeKey, ModeOpts)] = &[
(
ModeKey::Web,
ModeOpts::fill(ModeKey::Web, |o| {
o.node_n = Some(f32::INFINITY);
o.signals = Some(1.0e12);
}),
),
(
ModeKey::Globe,
ModeOpts::fill(ModeKey::Globe, |o| {
o.lat_rings = Some(0.0);
o.lon_density = Some(5_000.0);
}),
),
(
ModeKey::Rubik,
ModeOpts::fill(ModeKey::Rubik, |o| {
o.lat_rings = Some(0.0);
o.move_count = Some(1.0e7);
}),
),
(
ModeKey::Wave,
ModeOpts::fill(ModeKey::Wave, |o| {
o.rings = Some(0.0);
o.lon_density = Some(f32::NAN);
}),
),
(
ModeKey::Orbits,
ModeOpts::fill(ModeKey::Orbits, |o| {
o.orbit_n = Some(f32::INFINITY);
o.ghost_n = Some(1.0e9);
o.particles = Some(1.0e6);
}),
),
(
ModeKey::Morph,
ModeOpts::fill(ModeKey::Morph, |o| {
o.icon_d = Some(1.0e6);
}),
),
(
ModeKey::Ribbon,
ModeOpts::fill(ModeKey::Ribbon, |o| {
o.lanes = Some(1.0e6);
o.segs = Some(1.0e6);
o.band_mul = Some(1.0e6);
o.ghost_n = Some(1.0e9);
}),
),
(
ModeKey::Braid,
ModeOpts::fill(ModeKey::Braid, |o| {
o.strand_n = Some(1.0e9);
o.ghost_n = Some(1.0e9);
}),
),
];
for (mode, opts) in cases {
let frame = draw_mode(*mode, 64.0, 1.25, opts);
assert!(
frame.dots.len() <= 80_000,
"{mode:?} emitted {} dots — sanitize failed",
frame.dots.len()
);
for d in &frame.dots {
assert!(d.x.is_finite() && d.y.is_finite() && d.z.is_finite() && d.r.is_finite());
}
for l in &frame.lines {
assert!(l.x1.is_finite() && l.y1.is_finite() && l.x2.is_finite() && l.y2.is_finite());
}
}
let morph = draw_mode(
ModeKey::Morph,
64.0,
0.6,
&ModeOpts::fill(ModeKey::Morph, |o| {
o.icon_d = Some(MAX_ICON_D * 100.0);
}),
);
assert!(morph.dots.len() <= MAX_MORPH_DOTS);
let web = draw_mode(
ModeKey::Web,
64.0,
1.0,
&ModeOpts::fill(ModeKey::Web, |o| {
o.node_n = Some(MAX_NODE_N * 10.0);
}),
);
assert!(web.dots.len() < MAX_NODE_N as usize + 100);
let clean = sanitize_mode_opts(&ModeOpts::fill(ModeKey::Web, |o| {
o.node_n = Some(f32::INFINITY);
o.lat_rings = Some(-3.0);
o.icon_d = Some(f32::NAN);
}));
assert_eq!(clean.node_n, None); assert_eq!(clean.lat_rings, Some(1.0)); assert_eq!(clean.icon_d, None);
}