145 lines
4.4 KiB
C
145 lines
4.4 KiB
C
#include <assert.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
|
|
#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;
|
|
}
|