You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
6.0 KiB
177 lines
6.0 KiB
#include <catch2/catch_test_macros.hpp> |
|
#include "../src/physics.h" |
|
#include "../src/simulation.h" |
|
#include "../src/config_loader.h" |
|
#include <cmath> |
|
#include <vector> |
|
|
|
struct ParentHistory { |
|
std::vector<int> planet_a_parents; |
|
std::vector<int> planet_b_parents; |
|
}; |
|
|
|
TEST_CASE("Invalid parent: Earth should not become child of spacecraft", |
|
"[init][parent][bug]") { |
|
const double TIME_STEP = 60.0; |
|
|
|
SimulationState* sim = create_simulation(10, TIME_STEP); |
|
REQUIRE(load_system_config(sim, "tests/configs/earth_mars_simple.toml")); |
|
|
|
const int EARTH_IDX = 1; |
|
const int SPACECRAFT_IDX = 3; |
|
const int SUN_IDX = 0; |
|
|
|
REQUIRE(sim->bodies[EARTH_IDX].parent_index == SUN_IDX); |
|
|
|
for (int step = 0; step < 10; step++) { |
|
update_simulation(sim); |
|
|
|
int earth_parent = sim->bodies[EARTH_IDX].parent_index; |
|
|
|
INFO("Step " << step << ": Earth's parent = " << earth_parent |
|
<< " (" << (earth_parent == SPACECRAFT_IDX ? "SPACECRAFT" : |
|
earth_parent == SUN_IDX ? "Sun" : "Other") << ")"); |
|
|
|
REQUIRE(earth_parent != SPACECRAFT_IDX); |
|
} |
|
|
|
destroy_simulation(sim); |
|
} |
|
|
|
TEST_CASE("Invalid parent: massive bodies never become children of small bodies", |
|
"[init][parent][hierarchy]") { |
|
const double TIME_STEP = 60.0; |
|
const double MASS_THRESHOLD_RATIO = 1000.0; |
|
|
|
SimulationState* sim = create_simulation(10, TIME_STEP); |
|
REQUIRE(load_system_config(sim, "tests/configs/earth_mars_simple.toml")); |
|
|
|
for (int i = 0; i < sim->body_count; i++) { |
|
if (sim->bodies[i].parent_index >= 0) { |
|
int parent_idx = sim->bodies[i].parent_index; |
|
double parent_mass = sim->bodies[parent_idx].mass; |
|
double child_mass = sim->bodies[i].mass; |
|
double mass_ratio = parent_mass / child_mass; |
|
|
|
INFO("Body " << i << " (" << sim->bodies[i].name |
|
<< ") parent " << parent_idx << " (" << sim->bodies[parent_idx].name |
|
<< "): mass ratio = " << mass_ratio); |
|
|
|
REQUIRE(mass_ratio >= 1.0); |
|
|
|
if (strcmp(sim->bodies[parent_idx].name, "Spacecraft") != 0 && |
|
strcmp(sim->bodies[i].name, "Spacecraft") != 0) { |
|
REQUIRE(mass_ratio >= MASS_THRESHOLD_RATIO); |
|
} |
|
} |
|
} |
|
|
|
for (int step = 0; step < 100; step++) { |
|
update_simulation(sim); |
|
|
|
for (int i = 0; i < sim->body_count; i++) { |
|
if (sim->bodies[i].parent_index >= 0) { |
|
int parent_idx = sim->bodies[i].parent_index; |
|
double parent_mass = sim->bodies[parent_idx].mass; |
|
double child_mass = sim->bodies[i].mass; |
|
|
|
if (child_mass > 1e20) { |
|
REQUIRE(parent_mass > child_mass); |
|
} |
|
} |
|
} |
|
} |
|
|
|
destroy_simulation(sim); |
|
} |
|
|
|
TEST_CASE("Invalid parent: detect placeholder config values", |
|
"[init][config][validation]") { |
|
const double TIME_STEP = 60.0; |
|
|
|
SimulationState* sim = create_simulation(10, TIME_STEP); |
|
REQUIRE(load_system_config(sim, "tests/configs/earth_mars_simple.toml")); |
|
|
|
const int EARTH_IDX = 1; |
|
const int SPACECRAFT_IDX = 3; |
|
|
|
Vec3 craft_pos = sim->bodies[SPACECRAFT_IDX].position; |
|
Vec3 earth_pos = sim->bodies[EARTH_IDX].position; |
|
|
|
double distance = vec3_distance(craft_pos, earth_pos); |
|
|
|
INFO("Distance Earth <-> Spacecraft: " << distance << " m"); |
|
INFO("Earth position: (" << earth_pos.x << ", " << earth_pos.y << ", " << earth_pos.z << ")"); |
|
INFO("Spacecraft position: (" << craft_pos.x << ", " << craft_pos.y << ", " << craft_pos.z << ")"); |
|
|
|
REQUIRE(distance > 100000.0); |
|
|
|
destroy_simulation(sim); |
|
} |
|
|
|
TEST_CASE("Mutual SOI: similar mass planets within SOI boundary", |
|
"[init][soi][mutual][edge_case]") { |
|
const double TIME_STEP = 60.0; |
|
|
|
SimulationState* sim = create_simulation(10, TIME_STEP); |
|
REQUIRE(load_system_config(sim, "tests/configs/mutual_soi_close.toml")); |
|
|
|
const int PLANET_A_IDX = 1; |
|
const int PLANET_B_IDX = 2; |
|
const int SUN_IDX = 0; |
|
|
|
double planet_a_soi = sim->bodies[PLANET_A_IDX].soi_radius; |
|
double planet_b_soi = sim->bodies[PLANET_B_IDX].soi_radius; |
|
double separation = vec3_distance(sim->bodies[PLANET_A_IDX].position, |
|
sim->bodies[PLANET_B_IDX].position); |
|
|
|
INFO("PlanetA SOI: " << planet_a_soi / 1e9 << " million km"); |
|
INFO("PlanetB SOI: " << planet_b_soi / 1e9 << " million km"); |
|
INFO("Separation: " << separation / 1e9 << " million km"); |
|
|
|
REQUIRE(separation < planet_a_soi); |
|
REQUIRE(separation < planet_b_soi); |
|
|
|
ParentHistory history; |
|
|
|
for (int step = 0; step < 10000; step++) { |
|
update_simulation(sim); |
|
|
|
history.planet_a_parents.push_back(sim->bodies[PLANET_A_IDX].parent_index); |
|
history.planet_b_parents.push_back(sim->bodies[PLANET_B_IDX].parent_index); |
|
|
|
if (step > 0) { |
|
int prev_a = history.planet_a_parents[step-1]; |
|
int curr_a = history.planet_a_parents[step]; |
|
if (prev_a != curr_a) { |
|
INFO("Step " << step << ": PlanetA parent " << prev_a |
|
<< " -> " << curr_a); |
|
} |
|
|
|
int prev_b = history.planet_b_parents[step-1]; |
|
int curr_b = history.planet_b_parents[step]; |
|
if (prev_b != curr_b) { |
|
INFO("Step " << step << ": PlanetB parent " << prev_b |
|
<< " -> " << curr_b); |
|
} |
|
} |
|
} |
|
|
|
int final_parent_a = sim->bodies[PLANET_A_IDX].parent_index; |
|
int final_parent_b = sim->bodies[PLANET_B_IDX].parent_index; |
|
|
|
INFO("Final parent PlanetA: " << final_parent_a); |
|
INFO("Final parent PlanetB: " << final_parent_b); |
|
|
|
REQUIRE(final_parent_a == SUN_IDX); |
|
REQUIRE(final_parent_b == SUN_IDX); |
|
|
|
for (size_t i = 0; i < history.planet_a_parents.size(); i++) { |
|
REQUIRE(history.planet_a_parents[i] != PLANET_B_IDX); |
|
} |
|
for (size_t i = 0; i < history.planet_b_parents.size(); i++) { |
|
REQUIRE(history.planet_b_parents[i] != PLANET_A_IDX); |
|
} |
|
|
|
destroy_simulation(sim); |
|
}
|
|
|