//! **Reproducir una escena que llegó por el cable, ¿da los mismos píxeles que //! componerla acá?** //! //! El IR de escena (W4) tiene round-trip **estructural** certificado: //! `llimphi-wire-escena/src/pruebas.rs` verifica que cada variante sobreviva la //! serialización, que el texto viaje sin shapear, que el degradé conserve sus //! paradas. Lo que **no** verificaba nadie es que reproducir esas órdenes //! **dibuje lo mismo**. Un reproductor que aplicara las transformaciones en //! otro orden, o que remapeara mal un estilo internado, pasaría todos los tests //! estructurales y pintaría otra cosa. //! //! Acá los dos caminos terminan en el **mismo** rasterizador (`vello_cpu`) y //! sobre el **mismo** árbol (`escena_patron.rs`), así que lo que se exige no es //! una tolerancia sino **igualdad bit a bit**: cualquier diferencia es un error //! del emisor o del reproductor, no del antialiasing. //! //! La escena de cable la produce `llimphi-jaula` (backend `wire`), que no puede //! vivir en este binario —los backends de `llimphi-text` son excluyentes—: //! //! ```bash //! ./scripts/check-llimphi-cpu-vs-gpu.sh //! ``` //! //! Sin los `.wire` el test se saltea, con el comando para generarlos. use llimphi_cpu::lienzo::FormatoPixel; use llimphi_wawa::Cascara; include!("../../escena_patron.rs"); fn volcado(c: &Cascara) -> Vec { let mut px = vec![0u8; (ANCHO * ALTO * 4) as usize]; c.volcar(&mut px, (ANCHO * 4) as usize, FormatoPixel::Rgba8); px } #[test] fn lo_que_llega_por_el_cable_se_pinta_igual_que_lo_compuesto_aca() { let Ok(dir) = std::env::var("LLIMPHI_WIRE_DUMP") else { eprintln!( "salteado: faltan las escenas de cable. Generalas con\n \ ./scripts/check-llimphi-cpu-vs-gpu.sh" ); return; }; let dir = std::path::PathBuf::from(dir); let mut cascara = Cascara::new(ANCHO as u16, ALTO as u16); let mut probados = 0; for (nombre, vista) in patrones::<()>() { // El patrón de texto no cruza el cable en esta prueba: medir una cadena // es una pregunta que contesta este lado, y el emisor no puede // responderla solo. Ver el encabezado de `emitir_patron.rs`. let Ok(bytes) = std::fs::read(dir.join(format!("{nombre}.wire"))) else { continue; }; cascara.fotograma(vista); let directo = volcado(&cascara); let wire: llimphi_wire_escena::EscenaWire = postcard::from_bytes(&bytes).expect("deserializar la escena de cable"); let st = cascara.fotograma_wire(&wire); let por_cable = volcado(&cascara); let distintos = directo .chunks_exact(4) .zip(por_cable.chunks_exact(4)) .filter(|(a, b)| a != b) .count(); // Evidencia por texto (Regla 8): el número queda impreso corra o falle. println!( "{nombre:8} · {} bytes de cable · {} órdenes ({} salteadas) · {distintos} px distintos", bytes.len(), st.ejecutadas, st.salteadas ); assert_eq!( distintos, 0, "{nombre}: reproducir la escena del cable pintó algo distinto de \ componerla acá — mismo rasterizador, así que es el cable" ); // Guarda del arnés: una escena vacía se reproduce «igual» a la nada y // el test pasaría sin haber comparado un dibujo. assert!( st.ejecutadas > 0, "{nombre}: la escena del cable llegó sin una sola orden" ); // Y el reproductor tiene un contador propio para lo que no supo // ejecutar. Cero píxeles distintos con órdenes salteadas sería la // combinación más engañosa que hay: dos escenas igual de incompletas. assert_eq!( st.salteadas, 0, "{nombre}: el reproductor salteó {} órdenes", st.salteadas ); probados += 1; } assert!( probados >= 4, "sólo {probados} patrones cruzaron el cable; el arnés no está probando" ); }