librebound-sys 4.6.0

Raw FFI bindings and safe RAII wrappers for the REBOUND N-body integrator
Documentation
//! FFI smoke tests — exercise the REBOUND C library directly.
//!
//! These tests run in CI on every build and verify that:
//! - REBOUND links correctly against the vendored sources.
//! - Our RAII wrappers round-trip the FFI without leaking or double-freeing.
//! - Error mapping from REBOUND status codes works as expected.

use librebound_sys::{Simulation, ffi};

/// Two-body Kepler orbit under REBOUND defaults (G = 1, IAS15, gravity basic).
///
/// A unit-mass central body at the origin and a massless test particle on a
/// circular orbit of radius 1 with tangential velocity 1. After integrating
/// one period (2π) the test particle must return near its starting position.
#[test]
fn two_body_kepler() {
    let mut sim = Simulation::new().expect("Simulation::new");
    sim.set_exact_finish_time(true);

    sim.add_particle(ffi::reb_particle {
        m: 1.0,
        ..Default::default()
    });
    sim.add_particle(ffi::reb_particle {
        x: 1.0,
        vy: 1.0,
        ..Default::default()
    });
    assert_eq!(sim.n_particles(), 2);

    sim.integrate(2.0 * std::f64::consts::PI).unwrap();
    assert!((sim.t() - 2.0 * std::f64::consts::PI).abs() < 1e-12);

    let particles = sim.particles();
    let (x, y) = (particles[1].x, particles[1].y);
    assert!(
        (x - 1.0).abs() < 1e-8 && y.abs() < 1e-8,
        "expected ≈(1.0, 0.0) after one period, got ({x}, {y})"
    );
}

#[test]
fn integrate_empty_sim_errors_with_no_particles() {
    let mut sim = Simulation::new().expect("Simulation::new");
    let err = sim.integrate(1.0).unwrap_err();
    assert!(matches!(err, librebound_sys::Error::NoParticles));
}