#include #include #include #include "gps/gps_ephemeris_cache.h" static gps_ephemeris_t make_ephemeris( unsigned int prn, unsigned char iode) { gps_ephemeris_t ephemeris; memset(&ephemeris, 0, sizeof(ephemeris)); ephemeris.SVID = (unsigned char)prn; ephemeris.iode = iode; ephemeris.ephemeris_valid = true; ephemeris.toe.week = 2430; ephemeris.toe.sec = 123456.0; return ephemeris; } static void test_store_restore_and_expiry(void) { gps_ephemeris_cache_t cache; gps_ephemeris_cache_init(&cache, 100u); gps_ephemeris_t input = make_ephemeris(4u, 17u); gps_ephemeris_t output; memset(&output, 0, sizeof(output)); assert(gps_ephemeris_cache_store( &cache, 4u, &input, 1000u)); input.iode = 99u; assert(gps_ephemeris_cache_restore( &cache, 4u, 1100u, &output)); assert(output.iode == 17u); assert(output.SVID == 4u); assert(!gps_ephemeris_cache_restore( &cache, 4u, 1101u, &output)); /* Expiration invalidates the slot, not only this read. */ assert(!gps_ephemeris_cache_restore( &cache, 4u, 1001u, &output)); } static void test_validation_independence_and_invalidate(void) { gps_ephemeris_cache_t cache; gps_ephemeris_cache_init(&cache, 500u); gps_ephemeris_t prn4 = make_ephemeris(4u, 21u); gps_ephemeris_t prn19 = make_ephemeris(19u, 44u); gps_ephemeris_t output; prn4.ephemeris_valid = false; assert(!gps_ephemeris_cache_store( &cache, 4u, &prn4, 0u)); prn4.ephemeris_valid = true; assert(!gps_ephemeris_cache_store( &cache, 5u, &prn4, 0u)); assert(!gps_ephemeris_cache_store( &cache, GPS_PRN_COUNT, &prn4, 0u)); assert(gps_ephemeris_cache_store( &cache, 4u, &prn4, 20u)); assert(gps_ephemeris_cache_store( &cache, 19u, &prn19, 30u)); assert(gps_ephemeris_cache_restore( &cache, 19u, 40u, &output)); assert(output.iode == 44u); gps_ephemeris_cache_invalidate(&cache, 4u); assert(!gps_ephemeris_cache_restore( &cache, 4u, 40u, &output)); assert(gps_ephemeris_cache_restore( &cache, 19u, 40u, &output)); } static void test_repeated_issue_does_not_hide_staleness(void) { gps_ephemeris_cache_t cache; gps_ephemeris_cache_init(&cache, 100u); gps_ephemeris_t issue17 = make_ephemeris(6u, 17u); gps_ephemeris_t output; assert(gps_ephemeris_cache_store( &cache, 6u, &issue17, 1000u)); assert(gps_ephemeris_cache_store( &cache, 6u, &issue17, 1090u)); assert(!gps_ephemeris_cache_restore( &cache, 6u, 1101u, &output)); /* A changed IOD is a fresh broadcast issue and receives a new TTL. */ issue17.iode = 18u; issue17.iodc = 18u; assert(gps_ephemeris_cache_store( &cache, 6u, &issue17, 1200u)); assert(gps_ephemeris_cache_restore( &cache, 6u, 1300u, &output)); assert(output.iode == 18u); } static void test_time_anchor_is_independent_and_short_lived(void) { gps_ephemeris_cache_t cache; gps_ephemeris_cache_init(&cache, 1000u); gps_ephemeris_t ephemeris = make_ephemeris(11u, 9u); gps_cached_time_anchor_t anchor = { .tow = {.week = 2430, .sec = 345678.0}, .raw_sample = 0xffff0000u, .corrected_sample = 4294901759.75, .week_valid = true, .valid = true }; gps_cached_time_anchor_t restored; /* An anchor cannot outlive or exist without its ephemeris slot. */ assert(!gps_ephemeris_cache_store_time_anchor( &cache, 11u, &anchor, 50u)); assert(gps_ephemeris_cache_store( &cache, 11u, &ephemeris, 50u)); assert(gps_ephemeris_cache_store_time_anchor( &cache, 11u, &anchor, 60u)); assert(gps_ephemeris_cache_restore_time_anchor( &cache, 11u, 170u, 110u, &restored)); assert(restored.tow.week == 2430); assert(restored.raw_sample == 0xffff0000u); assert(!gps_ephemeris_cache_restore_time_anchor( &cache, 11u, 171u, 110u, &restored)); /* The two-hour-class ephemeris remains usable after the short counter * anchor expires; firmware then waits for one fresh HOW, not SF1/2/3. */ assert(gps_ephemeris_cache_restore( &cache, 11u, 171u, &ephemeris)); } int main(void) { test_store_restore_and_expiry(); test_validation_independence_and_invalidate(); test_repeated_issue_does_not_hide_staleness(); test_time_anchor_is_independent_and_short_lived(); puts("gps ephemeris cache tests passed"); return 0; }