7.9 KiB
Test Plan: Invalid Parent Assignment Bug
Overview
Comprehensive test suite to capture and validate parent-child relationship bugs in orbital mechanics simulation.
Date: January 20, 2026
Status: Complete (Tests 1-3 resolved)
Related: docs/mission_planning.md FIXME section
Bug Diagnosis
Root Cause Identified
The Bug (Fixed): In tests/configs/earth_mars_simple.toml, spacecraft had placeholder values:
position = {1.496e11, 0, 0}(IDENTICAL to Earth)velocity = {0, 0, 0}(zero velocity)SOI = ~17.3 meters(calculated from mass=1kg)
What Happened:
- Config loaded with spacecraft at Earth's exact position
- During
find_dominant_body(1)for Earth:- Checks all bodies
- Finds spacecraft at distance = 0
0 < 17.3is TRUE- Sets Earth's parent to spacecraft!
Why Test Failed But GUI Failed Worse:
- Test calls
initialize_spacecraft_leo()→ spacecraft moved to proper LEO orbit (200km from Earth) - GUI never called this → placeholder values caused immediate bug
Solution Implemented
Config Validation in src/config_loader.cpp:
- Added validation loop after parsing bodies, before
initialize_bodies() - Validates that distance between body and parent ≥ parent.radius + body.radius
- Provides clear error message with actual and required distances
- Prevents loading invalid configs with bodies too close to their parents
Config Fix in tests/configs/earth_mars_simple.toml:
- Changed spacecraft position from
1.496e11(same as Earth) to1.49606571e11 - This places spacecraft at proper LEO altitude: Earth position + 6,571,000 m
- 6,571 km = Earth radius (6,371 km) + 200 km altitude
Test Cases
Test Case 1: Earth→Spacecraft Parent Switch
Purpose: Directly detect when Earth's parent becomes spacecraft (the exact bug from FIXME)
Actual Result: ✅ PASSES
How It Was Fixed:
- Config validation now rejects bodies starting at parent's position
- Spacecraft properly positioned at LEO altitude (6,571 km from Earth center)
find_dominant_body()never finds spacecraft at distance=0- Earth's parent remains Sun throughout simulation
Config: tests/configs/earth_mars_simple.toml
Key Assertion:
REQUIRE(sim->bodies[EARTH_IDX].parent_index != SPACECRAFT_IDX);
Test Case 2: Mass Hierarchy Validation
Purpose: Validate that massive bodies never become children of small bodies
Actual Result: ✅ PASSES
How It Was Fixed:
- Config validation ensures proper parent-child distance
- Mass hierarchy preserved throughout simulation
- Earth never becomes child of spacecraft or other bodies
Config: tests/configs/earth_mars_simple.toml
Key Assertions:
// Parent must be more massive
REQUIRE(mass_ratio >= 1.0);
// For planets: parent should be significantly more massive
if (not spacecraft) {
REQUIRE(mass_ratio >= 1000.0);
}
// Massive bodies should never have small bodies as parents
if (child_mass > 1e20) { // Planet-scale
REQUIRE(parent_mass > child_mass);
}
Test Case 3: Config Placeholder Validation
Purpose: Detect invalid config initialization (bodies starting too close together)
Actual Result: ✅ PASSES
How It Was Fixed:
- Test updated to use radius-based validation (matches config_loader logic)
- Spacecraft now at proper LEO position: 6,571,000 m from Earth center
- Validation: distance (6,571,000 m) ≥ Earth.radius + spacecraft.radius (6,372,000 m)
- Config validation catches any bodies positioned within parent's radius
Config: tests/configs/earth_mars_simple.toml
Key Assertion:
double min_distance = sim->bodies[EARTH_IDX].radius + sim->bodies[SPACECRAFT_IDX].radius;
REQUIRE(distance >= min_distance); // parent.radius + body.radius
Test Case 4: Mutual SOI - Similar Mass Planets
Purpose: Edge case: two Earth-like planets positioned within each other's SOI
Actual Result: ❌ STILL FAILS (separate issue, not fixed by spacecraft validation)
Config: tests/configs/mutual_soi_close.toml
Setup:
- PlanetA: mass = 5.972e24 kg, position = {1.496e11, 0, 0}
- PlanetB: mass = 5.972e24 kg, position = {1.501e11, 0, 0}
- Separation: 5e8 meters (500 million km)
- Planet SOI: ~9.25e8 meters (925 million km)
- Both planets within each other's SOI
Why This Fails:
- Both planets start with parent=0 (Sun)
- Both are within each other's SOI
find_dominant_body()logic selects closest body within SOI- Result: PlanetA selects PlanetB as parent, PlanetB selects PlanetA as parent
- Config validation passes (both are ≥ parent.radius + body.radius from Sun)
Key Assertions:
// Both should orbit Sun (not each other)
REQUIRE(sim->bodies[PLANET_A_IDX].parent_index == SUN_IDX);
REQUIRE(sim->bodies[PLANET_B_IDX].parent_index == SUN_IDX);
// Planets should never have each other as parents
for (int parent : history.planet_a_parents) {
REQUIRE(parent != PLANET_B_IDX);
}
for (int parent : history.planet_b_parents) {
REQUIRE(parent != PLANET_A_IDX);
}
Expected Behavior (Option A):
- Both planets should continue orbiting Sun
- Neither should become other's parent
- This requires future fix to
find_dominant_body()logic (mass hierarchy check)
Test Matrix
| Test Case | Config | Tests | Expected (Before Fix) | Actual Result |
|---|---|---|---|---|
| 1. Earth→Spacecraft | earth_mars_simple.toml | Parent assignment | FAIL | ✅ PASS |
| 2. Mass Hierarchy | earth_mars_simple.toml | Mass ratios | FAIL | ✅ PASS |
| 3. Config Validation | earth_mars_simple.toml | Separation distance | FAIL | ✅ PASS |
| 4. Mutual SOI | mutual_soi_close.toml | Edge case behavior | FAIL | ❌ FAIL (separate issue) |
Implementation
Test File
tests/test_invalid_parent_assignment.cpp
Test Config Files
tests/configs/earth_mars_simple.toml(existing)tests/configs/mutual_soi_close.toml(new)
Build Integration
Add to CMakeLists.txt or Makefile test targets
Implementation Summary
Solution Applied (Jan 20, 2026):
-
Config validation in
src/config_loader.cpp:- Validates parent-child distances before initialization
- Requires distance ≥ parent.radius + body.radius
- Prevents loading invalid configs
-
Config fix in
tests/configs/earth_mars_simple.toml:- Spacecraft position corrected to proper LEO altitude
- Position: 1.49606571e11 m (Earth position + 6,571,000 m offset)
- Velocity calculated by
initialize_bodies()usingsemi_major_axis = 6.571e6
-
Test updates in
tests/test_invalid_parent_assignment.cpp:- Test 3 updated to use radius-based validation
- Matches config_loader validation logic
Future Work
Current Status
Tests 1-3 are now passing. Test 4 continues to fail, documenting a separate mutual SOI issue.
Potential Fixes for Test 4
- Add mass hierarchy check to
find_dominant_body() - Prevent mutual SOI assignments for similar-mass bodies
- Detect and reject invalid configs at load time
- Implement proper N-body interaction or restricted 3-body solution
Enhanced Detection
- SOI overlap detection at config load time
- Automatic correction of invalid parent assignments
- Validation warnings for edge cases
References
docs/mission_planning.md:125-135- FIXME section describing bug (now resolved)src/config_loader.cpp:138-157- Config validation implementationtests/configs/earth_mars_simple.toml- Corrected spacecraft position (LEO altitude)src/simulation.cpp:64-107-find_dominant_body()implementationsrc/simulation.cpp:212-233-initialize_bodies()implementationtests/test_invalid_parent_assignment.cpp- Test suite implementation
Commits
0239cc1- Add test suite for invalid parent assignment bugs899fa3b- Add config validation for parent-child distances