#include #include #include #include "gps/gps_acq_manager.h" static gps_acq_manager_t make_manager( uint64_t retry_delay, uint64_t hot_retry_delay, uint64_t hot_window, unsigned int max_hot_streak) { gps_acq_manager_t manager; const gps_acq_manager_config_t config = { .retry_delay_ticks = retry_delay, .hot_retry_delay_ticks = hot_retry_delay, .hot_window_ticks = hot_window, .max_hot_streak = max_hot_streak }; gps_acq_manager_init(&manager, &config); return manager; } static unsigned int start_next( gps_acq_manager_t* manager, uint64_t now, bool expected_hot) { unsigned int prn = GPS_ACQ_MANAGER_INVALID_PRN; bool hot = !expected_hot; assert(gps_acq_manager_start_next(manager, now, &prn, &hot)); assert(hot == expected_hot); return prn; } static void test_cold_round_robin_and_retry_from_tick_zero(void) { gps_acq_manager_t manager = make_manager(5u, 5u, 100u, 4u); assert(gps_acq_manager_enable_cold(&manager, 0u)); assert(gps_acq_manager_enable_cold(&manager, 1u)); assert(gps_acq_manager_enable_cold(&manager, 2u)); assert(start_next(&manager, 0u, false) == 0u); /* A tick-zero attempt is real and must still observe retry delay. */ gps_acq_manager_mark_failed(&manager, 0u, 0u); assert(start_next(&manager, 0u, false) == 1u); gps_acq_manager_mark_failed(&manager, 1u, 0u); assert(start_next(&manager, 0u, false) == 2u); gps_acq_manager_mark_failed(&manager, 2u, 0u); unsigned int ignored; assert(!gps_acq_manager_start_next( &manager, 4u, &ignored, NULL)); assert(start_next(&manager, 5u, false) == 0u); } static void test_hot_priority_round_robin_and_cold_fairness(void) { gps_acq_manager_t manager = make_manager(1u, 1u, 100u, 2u); assert(gps_acq_manager_enable_cold(&manager, 0u)); assert(gps_acq_manager_enable_cold(&manager, 1u)); gps_acq_manager_mark_lost(&manager, 7u, 10u); gps_acq_manager_mark_lost(&manager, 8u, 10u); assert(start_next(&manager, 10u, true) == 7u); gps_acq_manager_mark_failed(&manager, 7u, 11u); assert(start_next(&manager, 11u, true) == 8u); gps_acq_manager_mark_failed(&manager, 8u, 12u); /* Two hot attempts force one cold discovery attempt. */ assert(start_next(&manager, 12u, false) == 0u); gps_acq_manager_mark_failed(&manager, 0u, 13u); assert(start_next(&manager, 13u, true) == 7u); } static void test_expired_hot_becomes_cold_and_tracking_is_excluded(void) { gps_acq_manager_t manager = make_manager(1u, 1u, 10u, 4u); assert(gps_acq_manager_enable_cold(&manager, 2u)); gps_acq_manager_mark_lost(&manager, 9u, 20u); unsigned int prn = start_next(&manager, 31u, false); assert(prn == 2u); gps_acq_manager_mark_tracking(&manager, prn); prn = start_next(&manager, 31u, false); assert(prn == 9u); gps_acq_manager_mark_acquired(&manager, prn); unsigned int ignored; assert(!gps_acq_manager_start_next( &manager, 100u, &ignored, NULL)); gps_acq_manager_mark_tracking(&manager, 9u); gps_acq_manager_mark_stale(&manager, 9u); assert(gps_acq_manager_state(&manager, 9u) == GPS_ACQ_PRN_STALE); gps_acq_manager_mark_lost(&manager, 9u, 101u); assert(gps_acq_manager_state(&manager, 9u) == GPS_ACQ_PRN_HOT); } static void test_invalid_inputs_are_safe(void) { gps_acq_manager_t manager = make_manager(1u, 1u, 10u, 0u); assert(!gps_acq_manager_enable_cold( &manager, GPS_ACQ_MANAGER_PRN_COUNT)); assert(gps_acq_manager_state( &manager, GPS_ACQ_MANAGER_PRN_COUNT) == GPS_ACQ_PRN_DISABLED); assert(!gps_acq_manager_start_next(NULL, 0u, NULL, NULL)); assert(gps_acq_manager_count_searchable(NULL) == 0u); } static void test_failed_hot_search_is_backed_off(void) { gps_acq_manager_t manager = make_manager(1u, 30u, 100u, 4u); assert(gps_acq_manager_enable_cold(&manager, 0u)); gps_acq_manager_mark_lost(&manager, 20u, 0u); assert(start_next(&manager, 0u, true) == 20u); gps_acq_manager_mark_failed(&manager, 20u, 5u); assert(start_next(&manager, 5u, false) == 0u); gps_acq_manager_mark_failed(&manager, 0u, 6u); assert(start_next(&manager, 7u, false) == 0u); gps_acq_manager_mark_failed(&manager, 0u, 8u); assert(start_next(&manager, 35u, true) == 20u); } int main(void) { test_cold_round_robin_and_retry_from_tick_zero(); test_hot_priority_round_robin_and_cold_fairness(); test_expired_hot_becomes_cold_and_tracking_is_excluded(); test_invalid_inputs_are_safe(); test_failed_hot_search_is_backed_off(); puts("gps acquisition manager tests passed"); return 0; }