use rand::SeedableRng;
use rand::rngs::StdRng;
use wafrift_evolution::evolution::{EvolutionEngine, GenePool};
use wafrift_evolution::types::{Budget, OracleVerdict};
fn engine_with_map_elites() -> EvolutionEngine {
let mut engine = EvolutionEngine::with_algorithm(
"map_elites",
GenePool::default_wafrift(),
StdRng::seed_from_u64(7),
Budget::default(),
)
.expect("map_elites is built-in");
let pool = engine.gene_pool.clone();
let pop: Vec<_> = (0..16)
.map(|i| {
let mut rng = StdRng::seed_from_u64(100 + i as u64);
wafrift_evolution::evolution::population::random_chromosome(&pool, &mut rng)
})
.collect();
engine.seed_population(pop);
engine
}
#[test]
fn map_elites_grid_fills_through_engine_round_trip() {
let mut engine = engine_with_map_elites();
let mut total_evals = 0_usize;
for _ in 0..50 {
let batch = engine.batch_candidates(4);
if batch.is_empty() {
break;
}
total_evals += batch.len();
let results: Vec<(usize, OracleVerdict)> = batch
.into_iter()
.enumerate()
.map(|(i, (id, _))| (id, OracleVerdict::from_bool(i % 2 == 0)))
.collect();
engine.submit_batch(results).expect("submit_batch");
engine.evolve();
}
assert!(
total_evals >= 50,
"expected the engine to issue at least 50 evals over 50 batches"
);
assert_eq!(
engine.stats.evaluations, total_evals,
"submit_batch must update stats.evaluations exactly once per result; \
pre-fix this still passed because the count is engine-side, but \
the next assertion is the real bug catcher"
);
let snapshot = engine.population_snapshot();
assert!(
!snapshot.is_empty(),
"MapElites population_snapshot is empty after {total_evals} evals — \
the algorithm's grid was never updated. Pre-fix bug confirmed."
);
}
#[test]
fn engine_in_flight_carries_algorithm_candidate_id() {
let mut engine = engine_with_map_elites();
let batch = engine.batch_candidates(2);
assert!(!batch.is_empty(), "fresh engine must yield candidates");
for (eval_id_usize, _) in &batch {
let eval_id = *eval_id_usize as u64;
let entry = engine
.in_flight
.get(&eval_id)
.expect("freshly issued eval_id must be in in_flight");
let (algorithm_id, _chromosome, _sent_at) = entry;
assert!(
*algorithm_id > 0,
"in_flight tuple must carry the algorithm's candidate.id \
(got {algorithm_id}); MapElites/NoveltySearch lookup keys on it"
);
}
}