blob: df26de1e9b85d1bb1b2015608b7644345308e717 [file]
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <sys/types.h>
#include <time.h>
#include "sntpd.c"
static uint64_t g_total_sleep_ms = 0;
static struct timeval g_updated_tv;
static struct timeval g_tv_to_return;
//override nanosleep
int nanosleep_mock(const struct timespec *tv_up, struct timespec *rem) {
(void)rem;
g_total_sleep_ms += ts_to_ms(tv_up);
return 0;
}
//override settimeofday
int settimeofday (const struct timeval* tv,
const struct timezone* tz) {
assert(tv);
g_updated_tv = *tv;
return 0;
}
int try_sync_time_mock_error(bool synced, sntp_gettime_fn sntp_gettime_fn_ptr) {
return -1;
}
int try_sync_time_mock_success(bool synced, sntp_gettime_fn sntp_gettime_fn_ptr) {
return 0;
}
int sntp_gettime_mock(struct timeval *tv_upd) {
assert(tv_upd);
*tv_upd = g_tv_to_return;
return 0;
}
void test_sync_loop_on_error() {
g_total_sleep_ms = 0;
bool synced = false;
unsigned long long retry_delay = INITIAL_RETRY_DELAY;
for(int i = 0; i < 20; i++) {
do_sync(&synced, &retry_delay, try_sync_time_mock_error, nanosleep_mock, NULL);
}
fprintf(stdout, "Total sleep time is %" PRId64 " ms.\n", g_total_sleep_ms);
assert(g_total_sleep_ms >= 10239500 && g_total_sleep_ms < 20479000);
}
void test_sync_loop_on_success() {
g_total_sleep_ms = 0;
bool synced = false;
unsigned long long retry_delay = INITIAL_RETRY_DELAY;
for(int i = 0; i < 20; i++) {
do_sync(&synced, &retry_delay, try_sync_time_mock_success, nanosleep_mock, NULL);
}
fprintf(stdout, "Total sleep time is %" PRId64 " ms.\n", g_total_sleep_ms);
assert(g_total_sleep_ms >= 12000000 && g_total_sleep_ms < 24000000);
}
void test_try_sync_time() {
//Set the time when synced is false.
unsigned long long time_ms;
g_updated_tv.tv_sec = 0;
g_updated_tv.tv_usec = 0;
g_tv_to_return.tv_usec = 0;
g_tv_to_return.tv_sec = 0;
int rv = try_sync_time(false, sntp_gettime_mock);
assert(rv == 0);
assert(g_updated_tv.tv_sec == 0);
assert(g_updated_tv.tv_usec == 0);
//Synced is true, and diff > MAX_TIME_DRIFT
//settimeofday should not be called.
g_updated_tv.tv_sec = 1234;
g_updated_tv.tv_usec = 123456;
g_tv_to_return.tv_sec = 0;
g_tv_to_return.tv_usec = 0;
rv = try_sync_time(true, sntp_gettime_mock);
assert(rv == 0);
assert(g_updated_tv.tv_sec == 1234);
assert(g_updated_tv.tv_usec == 123456);
//Synced is true, local clock lagging, diff < UPDATE_INTERVAL
//settimeofday should not be called.
g_updated_tv.tv_sec = 1234;
g_updated_tv.tv_usec = 123456;
assert(!gettimeofday(&g_tv_to_return, NULL));
time_ms = tv_to_ms(&g_tv_to_return);
time_ms += 456;
ms_to_tv(&g_tv_to_return, time_ms);
rv = try_sync_time(true, sntp_gettime_mock);
assert(rv == 0);
assert(g_updated_tv.tv_sec == 1234);
assert(g_updated_tv.tv_usec == 123456);
//Synced is true, local clock ahead, diff < UPDATE_INTERVAL
//settimeofday should not be called.
g_updated_tv.tv_sec = 1234;
g_updated_tv.tv_usec = 123456;
assert(!gettimeofday(&g_tv_to_return, NULL));
time_ms = tv_to_ms(&g_tv_to_return);
time_ms -= 456;
ms_to_tv(&g_tv_to_return, time_ms);
rv = try_sync_time(true, sntp_gettime_mock);
assert(rv == 0);
assert(g_updated_tv.tv_sec == 1234);
assert(g_updated_tv.tv_usec == 123456);
//Synced is true, local clock lagging, UPDATE_INTERVAL < diff < MAX_TIME_DRIFT
g_updated_tv.tv_sec = 1234;
g_updated_tv.tv_usec = 123456;
assert(!gettimeofday(&g_tv_to_return, NULL));
time_ms = tv_to_ms(&g_tv_to_return);
time_ms += 501;
ms_to_tv(&g_tv_to_return, time_ms);
rv = try_sync_time(true, sntp_gettime_mock);
assert(rv == 0);
assert(g_updated_tv.tv_sec == g_tv_to_return.tv_sec);
assert(g_updated_tv.tv_usec == g_tv_to_return.tv_usec);
//Synced is true, local clock ahead, UPDATE_INTERVAL < diff < MAX_TIME_DRIFT
g_updated_tv.tv_sec = 1234;
g_updated_tv.tv_usec = 123456;
assert(!gettimeofday(&g_tv_to_return, NULL));
time_ms = tv_to_ms(&g_tv_to_return);
time_ms -= 501;
ms_to_tv(&g_tv_to_return, time_ms);
rv = try_sync_time(true, sntp_gettime_mock);
assert(rv == 0);
assert(g_updated_tv.tv_sec == g_tv_to_return.tv_sec);
assert(g_updated_tv.tv_usec == g_tv_to_return.tv_usec);
//Synced is true, local clock ahead, UPDATE_INTERVAL < diff < MAX_TIME_DRIFT
g_updated_tv.tv_sec = 1234;
g_updated_tv.tv_usec = 123456;
assert(!gettimeofday(&g_tv_to_return, NULL));
time_ms = tv_to_ms(&g_tv_to_return);
time_ms -= 17975;
ms_to_tv(&g_tv_to_return, time_ms);
rv = try_sync_time(true, sntp_gettime_mock);
assert(rv == 0);
assert(g_updated_tv.tv_sec == g_tv_to_return.tv_sec);
assert(g_updated_tv.tv_usec == g_tv_to_return.tv_usec);
//Synced is true, local clock lagging, UPDATE_INTERVAL < diff < MAX_TIME_DRIFT
g_updated_tv.tv_sec = 1234;
g_updated_tv.tv_usec = 123456;
assert(!gettimeofday(&g_tv_to_return, NULL));
time_ms = tv_to_ms(&g_tv_to_return);
time_ms += 11221;
ms_to_tv(&g_tv_to_return, time_ms);
rv = try_sync_time(true, sntp_gettime_mock);
assert(rv == 0);
assert(g_updated_tv.tv_sec == g_tv_to_return.tv_sec);
assert(g_updated_tv.tv_usec == g_tv_to_return.tv_usec);
}
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
test_sync_loop_on_success();
test_sync_loop_on_error();
test_try_sync_time();
return 0;
}