use planetsfactory::config::parameters::*;
use planetsfactory::engine::evolution::*;
use planetsfactory::engine::formation::*;
use planetsfactory::engine::generator::*;
use planetsfactory::engine::orbits::*;
use planetsfactory::observables::photometry::*;
use planetsfactory::observables::radial_velocity::*;
use planetsfactory::observables::transits::*;
#[test]
fn kepler_solver_circular() {
let ea = solve_kepler(1.0, 0.0, 1e-14);
assert!((ea - 1.0).abs() < 1e-12);
}
#[test]
fn kepler_solver_eccentric() {
let ea = solve_kepler(1.0, 0.5, 1e-14);
let check = ea - 0.5 * ea.sin();
assert!((check - 1.0).abs() < 1e-12);
}
#[test]
fn true_anomaly_at_periapsis() {
let nu = true_from_eccentric(0.0, 0.5);
assert!(nu.abs() < 1e-12);
}
#[test]
fn elements_to_state_earth_distance() {
let earth = OrbitalElements::from_au_deg(1.0, 0.0167, 0.0, 0.0, 0.0, 0.0);
let (pos, _vel) = elements_to_state(&earth, SOLAR_MASS);
let r = (pos[0] * pos[0] + pos[1] * pos[1] + pos[2] * pos[2]).sqrt();
assert!((r / AU - 1.0).abs() < 0.02);
}
#[test]
fn vis_viva_circular() {
let v = vis_viva(G * SOLAR_MASS, AU, AU);
let expected = (G * SOLAR_MASS / AU).sqrt();
assert!((v - expected).abs() / expected < 1e-10);
}
#[test]
fn hohmann_delta_v_positive() {
let (dv1, dv2) = hohmann_delta_v(G * SOLAR_MASS, AU, 1.524 * AU);
assert!(dv1 > 0.0 && dv2 > 0.0);
}
#[test]
fn orbital_period_consistent() {
let elem = OrbitalElements::from_au_deg(1.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let p = elem.period(G * SOLAR_MASS);
assert!((p / YEAR - 1.0).abs() < 0.01);
}
#[test]
fn formation_new_isolation_mass_positive() {
let f = FormationModel::new(
FormationChannel::CoreAccretion,
0.01 * SOLAR_MASS,
SOLAR_MASS,
0.02,
2.7,
);
let m = f.isolation_mass(1.0);
assert!(m > 0.0);
}
#[test]
fn formation_solar_like_snow_line_in_range() {
let f = FormationModel::solar_like();
assert!(f.snow_line_au > 2.0 && f.snow_line_au < 4.0);
}
#[test]
fn formation_critical_core_mass() {
let f = FormationModel::solar_like();
assert!(f.critical_core_mass() > 5.0 * EARTH_MASS);
}
#[test]
fn formation_gas_accretion_zero_below_critical() {
let f = FormationModel::solar_like();
assert!(f.runaway_gas_accretion_rate(EARTH_MASS) == 0.0);
}
#[test]
fn formation_gas_accretion_positive_above_critical() {
let f = FormationModel::solar_like();
assert!(f.runaway_gas_accretion_rate(20.0 * EARTH_MASS) > 0.0);
}
#[test]
fn formation_pebble_accretion_positive() {
let f = FormationModel::new(
FormationChannel::PebbleAccretion,
0.01 * SOLAR_MASS,
SOLAR_MASS,
0.02,
2.7,
);
assert!(f.pebble_accretion_rate(EARTH_MASS, 1.0) > 0.0);
}
#[test]
fn formation_timescale_positive() {
let f = FormationModel::solar_like();
assert!(f.formation_timescale(1.0) > 0.0);
}
#[test]
fn evolution_cooling_luminosity_positive() {
let e = PlanetEvolution::new(JUPITER_MASS, JUPITER_RADIUS, 5.2 * AU, SOLAR_LUMINOSITY);
assert!(e.cooling_luminosity() > 0.0);
}
#[test]
fn evolution_xuv_loss_positive() {
let e = PlanetEvolution::new(EARTH_MASS, EARTH_RADIUS, AU, SOLAR_LUMINOSITY);
assert!(e.xuv_mass_loss_rate(1e-3) > 0.0);
}
#[test]
fn evolution_impact_erosion_zero_below_escape() {
let f = PlanetEvolution::impact_erosion_fraction(5e3, 1.1e4);
assert!(f == 0.0);
}
#[test]
fn evolution_radius_at_age_gas_giant() {
let e = PlanetEvolution::new(JUPITER_MASS, JUPITER_RADIUS, 5.2 * AU, SOLAR_LUMINOSITY);
let r_young = e.radius_at_age(1e8 * YEAR);
let r_old = e.radius_at_age(5e9 * YEAR);
assert!(r_young > r_old);
}
#[test]
fn generator_solar_like_system() {
let config = SystemGeneratorConfig::solar_like(8);
let planets = generate_system(&config);
assert!(planets.len() == 8);
}
#[test]
fn generator_m_dwarf_system() {
let config = SystemGeneratorConfig::m_dwarf(5);
let planets = generate_system(&config);
assert!(planets.len() == 5);
}
#[test]
fn generator_hot_star_system() {
let config = SystemGeneratorConfig::hot_star(6);
let planets = generate_system(&config);
assert!(planets.len() == 6);
}
#[test]
fn generator_single_planet() {
let config = SystemGeneratorConfig::solar_like(1);
let planets = generate_system(&config);
assert!(planets.len() == 1);
}
#[test]
fn generator_custom_system() {
let config = SystemGeneratorConfig {
star_name: String::from("Proxima"),
star_mass: 0.12 * SOLAR_MASS,
star_temperature: 3042.0,
star_radius: 0.154 * SOLAR_RADIUS,
n_planets: 3,
inner_limit_au: 0.01,
outer_limit_au: 0.5,
frost_line_au: 0.05,
metallicity: 0.02,
seed: 123,
};
let planets = generate_system(&config);
assert!(planets.len() == 3);
}
#[test]
fn generator_produces_diverse_types() {
let config = SystemGeneratorConfig::solar_like(12);
let planets = generate_system(&config);
let mut has_terrestrial = false;
let mut has_giant = false;
let mut has_ice = false;
for p in &planets {
match p {
GeneratedPlanet::Terrestrial(_)
| GeneratedPlanet::SuperEarth(_)
| GeneratedPlanet::LavaWorld(_)
| GeneratedPlanet::OceanWorld(_) => has_terrestrial = true,
GeneratedPlanet::GasGiant(_) => has_giant = true,
GeneratedPlanet::IceGiant(_) | GeneratedPlanet::SubNeptune(_) => has_ice = true,
GeneratedPlanet::Rogue(_) => {}
}
}
assert!(has_terrestrial);
assert!(has_giant || has_ice);
}
#[test]
fn generator_rogue_planets() {
let rogues = generate_rogue_planets(5, 42);
assert!(rogues.len() == 5);
for p in &rogues {
match p {
GeneratedPlanet::Rogue(r) => {
assert!(r.mass > 0.0);
assert!(r.velocity > 0.0);
}
_ => panic!("expected rogue planet"),
}
}
}
#[test]
fn transit_depth_jupiter_like() {
let d = transit_depth(JUPITER_RADIUS, SOLAR_RADIUS);
assert!(d > 0.01 && d < 0.012);
}
#[test]
fn transit_probability_earth_like() {
let p = transit_probability(SOLAR_RADIUS, AU);
assert!(p > 0.004 && p < 0.005);
}
#[test]
fn rv_semi_amplitude_jupiter_like() {
let k = rv_semi_amplitude(
JUPITER_MASS,
SOLAR_MASS,
5.2 * AU,
0.048,
std::f64::consts::FRAC_PI_2,
);
assert!(k > 10.0 && k < 15.0);
}
#[test]
fn rv_minimum_mass_positive() {
let m = minimum_mass(0.09, SOLAR_MASS, YEAR, 0.017);
assert!(m > 0.0);
}
#[test]
fn photometry_flux_ratio_small() {
let r = planet_flux_ratio(JUPITER_RADIUS, 5.2 * AU, 0.34);
assert!(r > 0.0 && r < 1e-6);
}