-- de_ephemeris regression tests -- -- Tests the _de() function variants and VSOP87 fallback behavior. -- Since DE ephemeris files are not available in CI, these tests -- verify that fallback behavior is correct and produces identical -- results to the VSOP87 variants. \set boulder '''40.015N 105.270W 1655m'''::observer -- ============================================================ -- Test 1: pg_orrery_ephemeris_info() returns VSOP87 when no DE file -- The provider should be 'VSOP87' since no ephemeris_path is set. -- ============================================================ SELECT 'eph_info_vsop87' AS test, (pg_orrery_ephemeris_info()).provider AS provider; test | provider -----------------+---------- eph_info_vsop87 | VSOP87 (1 row) -- ============================================================ -- Test 2: planet_heliocentric_de falls back to VSOP87 -- Should produce identical results to planet_heliocentric() -- when DE is unavailable. -- ============================================================ SELECT 'helio_fallback' AS test, round(helio_x(planet_heliocentric(3, '2024-06-21 12:00:00+00'))::numeric, 8) = round(helio_x(planet_heliocentric_de(3, '2024-06-21 12:00:00+00'))::numeric, 8) AS x_match, round(helio_y(planet_heliocentric(3, '2024-06-21 12:00:00+00'))::numeric, 8) = round(helio_y(planet_heliocentric_de(3, '2024-06-21 12:00:00+00'))::numeric, 8) AS y_match, round(helio_z(planet_heliocentric(3, '2024-06-21 12:00:00+00'))::numeric, 8) = round(helio_z(planet_heliocentric_de(3, '2024-06-21 12:00:00+00'))::numeric, 8) AS z_match; test | x_match | y_match | z_match ----------------+---------+---------+--------- helio_fallback | t | t | t (1 row) -- ============================================================ -- Test 3: planet_heliocentric_de Sun at origin -- ============================================================ SELECT 'sun_origin_de' AS test, round(helio_x(planet_heliocentric_de(0, '2024-06-21 12:00:00+00'))::numeric, 10) AS x, round(helio_y(planet_heliocentric_de(0, '2024-06-21 12:00:00+00'))::numeric, 10) AS y, round(helio_z(planet_heliocentric_de(0, '2024-06-21 12:00:00+00'))::numeric, 10) AS z; test | x | y | z ---------------+--------------+--------------+-------------- sun_origin_de | 0.0000000000 | 0.0000000000 | 0.0000000000 (1 row) -- ============================================================ -- Test 4: planet_observe_de falls back to VSOP87 -- Elevation and azimuth should match planet_observe(). -- ============================================================ SELECT 'observe_fallback' AS test, round(topo_azimuth(planet_observe(5, :boulder, '2024-03-15 03:00:00+00'))::numeric, 4) = round(topo_azimuth(planet_observe_de(5, :boulder, '2024-03-15 03:00:00+00'))::numeric, 4) AS az_match, round(topo_elevation(planet_observe(5, :boulder, '2024-03-15 03:00:00+00'))::numeric, 4) = round(topo_elevation(planet_observe_de(5, :boulder, '2024-03-15 03:00:00+00'))::numeric, 4) AS el_match; test | az_match | el_match ------------------+----------+---------- observe_fallback | t | t (1 row) -- ============================================================ -- Test 5: sun_observe_de falls back to VSOP87 -- ============================================================ SELECT 'sun_fallback' AS test, round(topo_azimuth(sun_observe(:boulder, '2024-06-21 18:00:00+00'))::numeric, 4) = round(topo_azimuth(sun_observe_de(:boulder, '2024-06-21 18:00:00+00'))::numeric, 4) AS az_match, round(topo_elevation(sun_observe(:boulder, '2024-06-21 18:00:00+00'))::numeric, 4) = round(topo_elevation(sun_observe_de(:boulder, '2024-06-21 18:00:00+00'))::numeric, 4) AS el_match; test | az_match | el_match --------------+----------+---------- sun_fallback | t | t (1 row) -- ============================================================ -- Test 6: moon_observe_de falls back to ELP2000-82B -- ============================================================ SELECT 'moon_fallback' AS test, round(topo_azimuth(moon_observe(:boulder, '2024-06-21 18:00:00+00'))::numeric, 4) = round(topo_azimuth(moon_observe_de(:boulder, '2024-06-21 18:00:00+00'))::numeric, 4) AS az_match, round(topo_range(moon_observe(:boulder, '2024-06-21 18:00:00+00'))::numeric, 0) = round(topo_range(moon_observe_de(:boulder, '2024-06-21 18:00:00+00'))::numeric, 0) AS range_match; test | az_match | range_match ---------------+----------+------------- moon_fallback | t | t (1 row) -- ============================================================ -- Test 7: lambert_c3_de falls back to VSOP87 -- Earth-Mars 2024 window should match lambert_c3(). -- ============================================================ SELECT 'lambert_fallback' AS test, round(lambert_c3(3, 4, '2024-05-01 00:00:00+00', '2025-02-01 00:00:00+00')::numeric, 2) = round(lambert_c3_de(3, 4, '2024-05-01 00:00:00+00', '2025-02-01 00:00:00+00')::numeric, 2) AS c3_match; test | c3_match ------------------+---------- lambert_fallback | t (1 row) -- ============================================================ -- Test 8: lambert_transfer_de falls back to VSOP87 -- Should produce identical departure C3. -- ============================================================ SELECT 'transfer_fallback' AS test, round((lambert_transfer(3, 4, '2024-05-01 00:00:00+00', '2025-02-01 00:00:00+00')).c3_departure::numeric, 2) = round((lambert_transfer_de(3, 4, '2024-05-01 00:00:00+00', '2025-02-01 00:00:00+00')).c3_departure::numeric, 2) AS c3_match; test | c3_match -------------------+---------- transfer_fallback | t (1 row) -- ============================================================ -- Test 9: galilean_observe_de falls back to VSOP87 -- ============================================================ SELECT 'galilean_fallback' AS test, round(topo_elevation(galilean_observe(0, :boulder, '2024-03-15 03:00:00+00'))::numeric, 4) = round(topo_elevation(galilean_observe_de(0, :boulder, '2024-03-15 03:00:00+00'))::numeric, 4) AS el_match; test | el_match -------------------+---------- galilean_fallback | t (1 row) -- ============================================================ -- Test 10: saturn_moon_observe_de falls back to VSOP87 -- ============================================================ SELECT 'saturn_moon_fallback' AS test, round(topo_elevation(saturn_moon_observe(5, :boulder, '2024-06-15 04:00:00+00'))::numeric, 4) = round(topo_elevation(saturn_moon_observe_de(5, :boulder, '2024-06-15 04:00:00+00'))::numeric, 4) AS el_match; test | el_match ----------------------+---------- saturn_moon_fallback | t (1 row) -- ============================================================ -- Test 11: uranus_moon_observe_de falls back to VSOP87 -- ============================================================ SELECT 'uranus_moon_fallback' AS test, round(topo_elevation(uranus_moon_observe(3, :boulder, '2024-06-15 04:00:00+00'))::numeric, 4) = round(topo_elevation(uranus_moon_observe_de(3, :boulder, '2024-06-15 04:00:00+00'))::numeric, 4) AS el_match; test | el_match ----------------------+---------- uranus_moon_fallback | t (1 row) -- ============================================================ -- Test 12: mars_moon_observe_de falls back to VSOP87 -- ============================================================ SELECT 'mars_moon_fallback' AS test, round(topo_elevation(mars_moon_observe(0, :boulder, '2024-06-15 04:00:00+00'))::numeric, 4) = round(topo_elevation(mars_moon_observe_de(0, :boulder, '2024-06-15 04:00:00+00'))::numeric, 4) AS el_match; test | el_match --------------------+---------- mars_moon_fallback | t (1 row) -- ============================================================ -- Test 13: All DE planet functions work (fallback mode) -- Mercury through Neptune, all should return valid positions -- matching their VSOP87 counterparts. -- ============================================================ SELECT 'all_planets_de' AS test, body_id, round(helio_distance(planet_heliocentric_de(body_id, '2024-06-21 12:00:00+00'))::numeric, 2) AS dist_au FROM generate_series(1, 8) AS body_id; test | body_id | dist_au ----------------+---------+--------- all_planets_de | 1 | 0.33 all_planets_de | 2 | 0.72 all_planets_de | 3 | 1.02 all_planets_de | 4 | 1.40 all_planets_de | 5 | 5.02 all_planets_de | 6 | 9.69 all_planets_de | 7 | 19.59 all_planets_de | 8 | 29.90 (8 rows) -- ============================================================ -- Test 14: Error handling - invalid body_id -- ============================================================ SELECT 'invalid_body_de' AS test, planet_heliocentric_de(9, now()); ERROR: invalid body_id 9: must be 0 (Sun) or 1-8 (Mercury-Neptune) -- ============================================================ -- Test 15: Error handling - cannot observe Earth from Earth -- ============================================================ SELECT 'earth_error_de' AS test, planet_observe_de(3, :boulder, now()); ERROR: cannot observe Earth from Earth