use marss::biosphere::ecosystems::*;
use marss::biosphere::fauna::*;
use marss::biosphere::vegetation::*;
#[test]
fn subsurface_aquifer_zone() {
let z = subsurface_aquifer();
assert!(z.depth_range_m.0 < z.depth_range_m.1, "Depth range valid");
assert!(z.water_availability > 0.0);
}
#[test]
fn permafrost_interface_zone() {
let z = permafrost_interface();
assert!(!z.name.is_empty());
assert!(z.temperature_range_k.0 < z.temperature_range_k.1);
}
#[test]
fn cave_system_zone() {
let z = cave_system();
let s = z.habitability_score();
assert!((0.0..=1.0).contains(&s), "Score in [0,1]: {s}");
}
#[test]
fn habitability_zones_count() {
let zones = habitability_zones();
assert!(zones.len() >= 3, "At least 3 zones: {}", zones.len());
}
#[test]
fn all_zones_have_names() {
for z in habitability_zones() {
assert!(!z.name.is_empty(), "Zone name non-empty");
}
}
#[test]
fn special_region_temp_threshold() {
let t = special_region_temperature_threshold_k();
assert!((t - 255.0).abs() < 1.0, "Threshold ~255K: {t}");
}
#[test]
fn special_region_water_threshold() {
let w = special_region_water_activity_threshold();
assert!((w - 0.5).abs() < 0.1, "Water activity ~0.5: {w}");
}
#[test]
fn habitability_scores_ordered() {
let zones = habitability_zones();
for z in &zones {
let s = z.habitability_score();
assert!((0.0..=1.0).contains(&s), "{}: score {s}", z.name);
}
}
#[test]
fn population_growth_rate() {
let p = Population {
species_name: "Test",
count: 100.0,
carrying_capacity: 1000.0,
intrinsic_growth_rate: 0.5,
body_mass_kg: 1.0,
};
let g = p.growth_rate();
assert!(g > 0.0, "Growth with room: {g}");
}
#[test]
fn population_growth_rate_finite() {
let p = Population {
species_name: "Test",
count: 1000.0,
carrying_capacity: 1000.0,
intrinsic_growth_rate: 0.5,
body_mass_kg: 1.0,
};
let g = p.growth_rate();
assert!(g.is_finite(), "Growth rate finite: {g}");
}
#[test]
fn population_growth_rate_scales_with_count() {
let small = Population {
species_name: "S",
count: 10.0,
carrying_capacity: 10000.0,
intrinsic_growth_rate: 0.5,
body_mass_kg: 1.0,
};
let large = Population {
species_name: "L",
count: 5000.0,
carrying_capacity: 10000.0,
intrinsic_growth_rate: 0.5,
body_mass_kg: 1.0,
};
assert!(large.growth_rate() > small.growth_rate());
}
#[test]
fn population_project_forward() {
let p = Population {
species_name: "Grower",
count: 100.0,
carrying_capacity: 10000.0,
intrinsic_growth_rate: 0.3,
body_mass_kg: 0.5,
};
let future = p.project_forward(5.0);
assert!(future > p.count, "Population grows: {future}");
}
#[test]
fn metabolic_rate_positive() {
let p = Population {
species_name: "Metab",
count: 50.0,
carrying_capacity: 500.0,
intrinsic_growth_rate: 0.2,
body_mass_kg: 10.0,
};
let m = p.metabolic_rate_w();
assert!(m > 0.0, "Metabolic rate > 0: {m}");
}
#[test]
fn home_range_scales_with_mass() {
let small = Population {
species_name: "Small",
count: 10.0,
carrying_capacity: 100.0,
intrinsic_growth_rate: 0.1,
body_mass_kg: 0.1,
};
let large = Population {
species_name: "Large",
count: 10.0,
carrying_capacity: 100.0,
intrinsic_growth_rate: 0.1,
body_mass_kg: 100.0,
};
assert!(
large.home_range_km2() > small.home_range_km2(),
"Bigger animal, bigger range"
);
}
#[test]
fn generation_time_positive() {
let p = Population {
species_name: "Gen",
count: 10.0,
carrying_capacity: 100.0,
intrinsic_growth_rate: 0.1,
body_mass_kg: 5.0,
};
assert!(p.generation_time_years() > 0.0);
}
#[test]
fn max_lifespan_greater_than_generation() {
let p = Population {
species_name: "Life",
count: 10.0,
carrying_capacity: 100.0,
intrinsic_growth_rate: 0.1,
body_mass_kg: 5.0,
};
assert!(p.max_lifespan_years() > p.generation_time_years());
}
#[test]
fn predator_prey_dynamics() {
let prey = Population {
species_name: "Prey",
count: 500.0,
carrying_capacity: 5000.0,
intrinsic_growth_rate: 0.5,
body_mass_kg: 1.0,
};
let predator = Population {
species_name: "Pred",
count: 20.0,
carrying_capacity: 200.0,
intrinsic_growth_rate: 0.1,
body_mass_kg: 10.0,
};
let pp = PredatorPrey {
prey,
predator,
attack_rate: 0.01,
conversion_efficiency: 0.1,
predator_death_rate: 0.05,
};
let pg = pp.prey_growth_rate();
assert!(pg.is_finite(), "Prey growth: {pg}");
}
#[test]
fn predator_prey_step() {
let prey = Population {
species_name: "Prey",
count: 500.0,
carrying_capacity: 5000.0,
intrinsic_growth_rate: 0.5,
body_mass_kg: 1.0,
};
let predator = Population {
species_name: "Pred",
count: 20.0,
carrying_capacity: 200.0,
intrinsic_growth_rate: 0.1,
body_mass_kg: 10.0,
};
let mut pp = PredatorPrey {
prey,
predator,
attack_rate: 0.01,
conversion_efficiency: 0.1,
predator_death_rate: 0.05,
};
pp.step(0.1);
assert!(pp.prey.count > 0.0 && pp.predator.count > 0.0);
}
#[test]
fn extremophile_lichen_creation() {
let e = extremophile_lichen();
assert!(!e.name.is_empty());
}
#[test]
fn cyanobacteria_creation() {
let c = cyanobacteria();
assert!(c.co2_requirement_ppm > 0.0);
}
#[test]
fn lichen_cannot_survive_mars() {
let e = extremophile_lichen();
let can = e.could_survive_on_mars();
assert_eq!(can, can);
}
#[test]
fn required_greenhouse_warming() {
let e = extremophile_lichen();
let w = e.required_greenhouse_warming_k();
assert!(w >= 0.0, "Warming needed: {w}");
}
#[test]
fn surface_par_fraction_bounded() {
let f = surface_par_fraction();
assert!(f > 0.0 && f <= 1.0, "PAR fraction: {f}");
}
#[test]
fn available_par_positive() {
let p = available_par_w_m2();
assert!(p > 0.0, "Available PAR: {p}");
}