1#include "pico_sntp_client.h"
2#include "modules/pico_sntp_client.c"
3#include "check.h"
4#include "pico_socket.h"
5/* Mocking functions, variables, ... */
6volatile pico_time pico_tick = 0ull;
7volatile pico_err_t pico_err = 0;
8
9Suite *pico_suite(void);
10void cb_synced(pico_err_t status);
11
12/* Used in pico_sntp_sync_start */
13struct pico_socket *pico_socket_open(uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *s))
14{
15    struct pico_socket *sock = PICO_ZALLOC(sizeof(struct pico_socket));
16    (void) net;
17    (void) proto;
18    (void) wakeup;
19    fail_unless (sock != NULL);
20    return sock;
21}
22
23/* Used in pico_sntp_sync_start */
24int pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port)
25{
26    (void) s;
27    (void) local_addr;
28    (void) port;
29    return 0;
30}
31
32/* Used in pico_sntp_sync_start */
33int pico_socket_close(struct pico_socket *s)
34{
35    (void) s;
36    return 0;
37}
38
39/* Used in pico_sntp_send */
40int8_t pico_socket_del(struct pico_socket *s)
41{
42    (void) s;
43    return 0;
44}
45
46/* Used in dnsCallback */
47int pico_string_to_ipv4(const char *ipstr, uint32_t *ip)
48{
49    (void) ipstr;
50    (void) ip;
51    return 0;
52}
53
54/* Used in dnsCallback */
55int pico_string_to_ipv6(const char *ipstr, uint8_t *ip)
56{
57    (void) ipstr;
58    (void) ip;
59    return 0;
60}
61
62/* Used in pico_sntp_sync_start_ipv4 */
63int pico_ipv4_to_string(char* ipbuf, const uint32_t ip)
64{
65    (void) ipbuf;
66    (void) ip;
67    return 0;
68}
69
70/* Used in pico_sntp_sync_start_ipv6 */
71int pico_ipv6_to_string(char* ipbuf, const uint8_t ip[PICO_SIZE_IP6])
72{
73    (void) ipbuf;
74    (void) ip;
75    return 0;
76}
77
78/* Used in pico_sntp_client_wakeup */
79int pico_socket_recvfrom(struct pico_socket *s, void *buf, int len, void *orig, uint16_t *remote_port)
80{
81    (void) s;
82    (void) buf;
83    (void) len;
84    (void) orig;
85    (void) remote_port;
86    return 0;
87}
88
89/* Used in pico_sntp_send */
90int pico_socket_sendto(struct pico_socket *s, const void *buf, int len, void *dst, uint16_t remote_port)
91{
92    (void) s;
93    (void) buf;
94    (void) len;
95    (void) dst;
96    (void) remote_port;
97    return 0;
98}
99
100/* Used in pico_sntp_sync_start_dns_ipv4, not tested */
101int pico_dns_client_getaddr(const char *url, void (*callback)(char *ip, void *arg), void *arg)
102{
103    (void) url;
104    (void) callback;
105    (void) arg;
106    return 0;
107}
108
109/* Used in pico_sntp_sync_start_dns_ipv6, not tested */
110int pico_dns_client_getaddr6(const char *url, void (*callback)(char *, void *), void *arg)
111{
112    (void) url;
113    (void) callback;
114    (void) arg;
115    return 0;
116}
117
118/* Used in pico_sntp_parse */
119void cb_synced(pico_err_t status)
120{
121    (void) status;
122
123}
124
125/* Used in pico_sntp_send */
126static uint32_t timers_added = 0;
127uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
128{
129    (void) expire;
130    (void) timer;
131    (void) arg;
132    return ++timers_added;
133}
134
135/* Used in pico_sntp_cleanup */
136void pico_timer_cancel(uint32_t t)
137{
138    IGNORE_PARAMETER(t);
139}
140
141START_TEST(tc_timestamp_convert)
142{
143    struct pico_sntp_ts ts;
144    struct pico_timeval tv;
145    pico_time delay = 0ull;
146    int ret = 0;
147
148    /* Input is all zero */
149    ts.sec = long_be(0ul);
150    ts.frac = long_be(0ul);
151    ret = timestamp_convert(&ts, &tv, delay);
152    ck_assert(ret == -1);
153    ck_assert(tv.tv_sec == 0);
154    ck_assert(tv.tv_msec == 0);
155
156    /* Minimum input*/
157    ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
158    ts.frac = long_be(4310344ul);     /* MIN value: 1msec */
159    ret = timestamp_convert(&ts, &tv, delay);
160    ck_assert(ret == 0);
161    fail_unless(tv.tv_sec == 1390000000);
162    fail_unless(tv.tv_msec == 1);
163
164    /* Intermediate input */
165    ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
166    ts.frac = long_be(3865470566ul);    /* value: 899msec */
167    ret = timestamp_convert(&ts, &tv, delay);
168    ck_assert(ret == 0);
169    fail_unless(tv.tv_sec == 1390000000);
170    fail_unless(tv.tv_msec == 900);
171
172    /* Maximum input */
173    ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
174    ts.frac = long_be(4294967295ul);    /* MAX value: 999msec */
175    ret = timestamp_convert(&ts, &tv, delay);
176    ck_assert(ret == 0);
177    fail_unless(tv.tv_sec == 1390000001);
178    fail_unless(tv.tv_msec == 0);
179
180    /* Intermediate input with delay */
181    ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
182    ts.frac = long_be(3865470566ul);    /* value: 899msec */
183    delay = 200ull;
184    ret = timestamp_convert(&ts, &tv, delay);
185    ck_assert(ret == 0);
186    fail_unless(tv.tv_sec == 1390000001);
187    fail_unless(tv.tv_msec == 100);
188}
189END_TEST
190START_TEST(tc_pico_sntp_cleanup)
191{
192    struct sntp_server_ns_cookie *ck;
193    struct pico_socket *sock;
194    ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
195    fail_unless (ck != NULL);
196    ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
197    fail_unless (ck->hostname != NULL);
198    ck->stamp = 0ull;
199    ck->cb_synced = cb_synced;
200
201    sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
202    ck->sock = sock;
203    sock->priv = ck;
204
205
206    pico_sntp_cleanup(ck, PICO_ERR_NOERR);
207}
208END_TEST
209START_TEST(tc_pico_sntp_parse)
210{
211    /* TODO: test this: static void pico_sntp_parse(char *buf, struct sntp_server_ns_cookie *ck) */
212    struct sntp_server_ns_cookie *ck;
213    struct pico_socket *sock;
214    struct pico_sntp_header header = {
215        0
216    };
217
218    ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
219    fail_unless (ck != NULL);
220    ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
221    fail_unless (ck->hostname != NULL);
222    ck->stamp = 0ull;
223    ck->cb_synced = cb_synced;
224
225    sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
226    ck->sock = sock;
227    sock->priv = ck;
228
229    header.mode = 4;    /* server mode */
230    header.vn = 4;      /* sntp version 4 */
231    header.stratum = 1; /* primary reference */
232    header.trs_ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
233    header.trs_ts.frac = long_be(3865470566ul);    /* value: 899msec */
234
235    fail_if(pico_sntp_parse((char *) &header, NULL) == 0);
236    fail_if(pico_sntp_parse((char *) &header, ck) != 0);
237}
238END_TEST
239START_TEST(tc_pico_sntp_client_wakeup)
240{
241    /* TODO: test this: static void pico_sntp_client_wakeup(uint16_t ev, struct pico_socket *s) */
242    uint16_t event = PICO_SOCK_EV_ERR;
243    struct sntp_server_ns_cookie *ck;
244    struct pico_socket *sock;
245    ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
246    fail_unless (ck != NULL);
247    ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
248    fail_unless (ck->hostname != NULL);
249    ck->stamp = 0ull;
250    ck->cb_synced = cb_synced;
251
252    sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
253    ck->sock = sock;
254    sock->priv = ck;
255
256    ck->cb_synced = cb_synced;
257    printf("Started wakeup unit test\n");
258
259    pico_sntp_client_wakeup(event, sock);
260}
261END_TEST
262START_TEST(tc_sntp_receive_timeout)
263{
264    struct sntp_server_ns_cookie *ck;
265    struct pico_socket *sock;
266    ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
267    fail_unless (ck != NULL);
268    ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
269    fail_unless (ck->hostname != NULL);
270    ck->stamp = 0ull;
271    ck->cb_synced = cb_synced;
272
273    sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
274    ck->sock = sock;
275    sock->priv = ck;
276    sntp_receive_timeout(0ull, ck);
277
278}
279END_TEST
280START_TEST(tc_pico_sntp_send)
281{
282    /* TODO: test this: static void pico_sntp_send(struct pico_socket *sock, union pico_address *dst) */
283    struct pico_socket sock = {
284        0
285    };
286    union pico_address dst;
287    struct sntp_server_ns_cookie ck = {
288        0
289    };
290    sock.priv = &ck;
291
292    pico_sntp_send(&sock, &dst);
293}
294END_TEST
295START_TEST(tc_dnsCallback)
296{
297    /* TODO: test this: static void dnsCallback(char *ip, void *arg) */
298    char ip[] = "198.123.30.132";
299    struct sntp_server_ns_cookie *ck;
300    ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
301
302    dnsCallback(ip, ck);
303}
304END_TEST
305START_TEST(tc_pico_sntp_sync)
306{
307    const char *sntp_server= "ntp.nasa.gov";
308
309    fail_if(pico_sntp_sync(NULL, cb_synced) == 0);
310    fail_if(pico_err != PICO_ERR_EINVAL);
311
312    fail_if(pico_sntp_sync(sntp_server, NULL) == 0);
313    fail_if(pico_err != PICO_ERR_EINVAL);
314
315    fail_if(pico_sntp_sync(sntp_server, cb_synced) != 0);
316}
317END_TEST
318START_TEST(tc_pico_sntp_sync_ip)
319{
320    union pico_address sntp_addr = { .ip4.addr = 0ul };
321
322    fail_if(pico_sntp_sync_ip(NULL, cb_synced) == 0);
323    fail_if(pico_err != PICO_ERR_EINVAL);
324
325    fail_if(pico_sntp_sync_ip(&sntp_addr, NULL) == 0);
326    fail_if(pico_err != PICO_ERR_EINVAL);
327
328    fail_if(pico_sntp_sync_ip(&sntp_addr, cb_synced) != 0);
329}
330END_TEST
331START_TEST(tc_pico_sntp_sync_start)
332{
333    struct sntp_server_ns_cookie ck = { 0 };
334    union pico_address sntp_addr = { .ip4.addr= 0ul };
335
336    fail_if(pico_sntp_sync_start(&ck, &sntp_addr) != 0);
337}
338END_TEST
339START_TEST(tc_pico_sntp_sync_start_dns_ipv4)
340{
341    const char *sntp_server = "ntp.nasa.gov";
342
343    fail_if(pico_sntp_sync_start_dns_ipv4(sntp_server, cb_synced) != 0);
344}
345END_TEST
346START_TEST(tc_pico_sntp_sync_start_dns_ipv6)
347{
348    const char *sntp_server = "ntp.nasa.gov";
349
350    fail_if(pico_sntp_sync_start_dns_ipv6(sntp_server, cb_synced) != 0);
351}
352END_TEST
353START_TEST(tc_pico_sntp_sync_start_ipv4)
354{
355    union pico_address sntp_addr = { .ip4.addr = 0};
356
357    fail_if(pico_sntp_sync_start_ipv4(&sntp_addr, cb_synced) != 0);
358}
359END_TEST
360START_TEST(tc_pico_sntp_sync_start_ipv6)
361{
362    union pico_address sntp_addr = { .ip6.addr = { 0 } };
363
364    fail_if(pico_sntp_sync_start_ipv6(&sntp_addr, cb_synced) != 0);
365}
366END_TEST
367
368Suite *pico_suite(void)
369{
370    Suite *s = suite_create("PicoTCP");
371
372    TCase *TCase_timestamp_convert = tcase_create("Unit test for pico_timeval");
373    TCase *TCase_pico_sntp_cleanup = tcase_create("Unit test for pico_sntp_cleanup");
374    TCase *TCase_pico_sntp_send = tcase_create("Unit test for pico_sntp_send");
375    TCase *TCase_pico_sntp_parse = tcase_create("Unit test for pico_sntp_parse");
376    TCase *TCase_pico_sntp_client_wakeup = tcase_create("Unit test for pico_sntp_client_wakeup");
377    TCase *TCase_sntp_receive_timeout = tcase_create("Unit test for sntp_receive_timeout");
378    TCase *TCase_dnsCallback = tcase_create("Unit test for dnsCallback");
379    TCase *TCase_pico_sntp_sync = tcase_create("Unit test for pico_sntp_sync");
380    TCase *TCase_pico_sntp_sync_ip = tcase_create("Unit test for pico_sntp_sync_ip");
381    TCase *TCase_pico_sntp_sync_start = tcase_create("Unit test for pico_sntp_sync_start");
382    TCase *TCase_pico_sntp_sync_start_dns_ipv4 = tcase_create("Unit test for pico_sntp_sync_start_dns_ipv4");
383    TCase *TCase_pico_sntp_sync_start_dns_ipv6 = tcase_create("Unit test for pico_sntp_sync_start_dns_ipv6");
384    TCase *TCase_pico_sntp_sync_start_ipv4 = tcase_create("Unit test for pico_sntp_sync_start_ipv4");
385    TCase *TCase_pico_sntp_sync_start_ipv6 = tcase_create("Unit test for pico_sntp_sync_start_ipv6");
386
387
388    tcase_add_test(TCase_timestamp_convert, tc_timestamp_convert);
389    suite_add_tcase(s, TCase_timestamp_convert);
390    tcase_add_test(TCase_pico_sntp_cleanup, tc_pico_sntp_cleanup);
391    suite_add_tcase(s, TCase_pico_sntp_cleanup);
392    tcase_add_test(TCase_pico_sntp_parse, tc_pico_sntp_parse);
393    suite_add_tcase(s, TCase_pico_sntp_parse);
394    tcase_add_test(TCase_pico_sntp_client_wakeup, tc_pico_sntp_client_wakeup);
395    suite_add_tcase(s, TCase_pico_sntp_client_wakeup);
396    tcase_add_test(TCase_sntp_receive_timeout, tc_sntp_receive_timeout);
397    suite_add_tcase(s, TCase_sntp_receive_timeout);
398    tcase_add_test(TCase_pico_sntp_send, tc_pico_sntp_send);
399    suite_add_tcase(s, TCase_pico_sntp_send);
400    tcase_add_test(TCase_dnsCallback, tc_dnsCallback);
401    suite_add_tcase(s, TCase_dnsCallback);
402    tcase_add_test(TCase_pico_sntp_sync, tc_pico_sntp_sync);
403    suite_add_tcase(s, TCase_pico_sntp_sync);
404    tcase_add_test(TCase_pico_sntp_sync_ip, tc_pico_sntp_sync_ip);
405    suite_add_tcase(s, TCase_pico_sntp_sync_ip);
406    tcase_add_test(TCase_pico_sntp_sync_start, tc_pico_sntp_sync_start);
407    suite_add_tcase(s, TCase_pico_sntp_sync_start);
408    tcase_add_test(TCase_pico_sntp_sync_start_dns_ipv4, tc_pico_sntp_sync_start_dns_ipv4);
409    suite_add_tcase(s, TCase_pico_sntp_sync_start_dns_ipv4);
410    tcase_add_test(TCase_pico_sntp_sync_start_dns_ipv6, tc_pico_sntp_sync_start_dns_ipv6);
411    suite_add_tcase(s, TCase_pico_sntp_sync_start_dns_ipv6);
412    tcase_add_test(TCase_pico_sntp_sync_start_ipv4, tc_pico_sntp_sync_start_ipv4);
413    suite_add_tcase(s, TCase_pico_sntp_sync_start_ipv4);
414    tcase_add_test(TCase_pico_sntp_sync_start_ipv6, tc_pico_sntp_sync_start_ipv6);
415    suite_add_tcase(s, TCase_pico_sntp_sync_start_ipv6);
416    return s;
417}
418
419int main(void)
420{
421    int fails;
422    Suite *s = pico_suite();
423    SRunner *sr = srunner_create(s);
424    srunner_run_all(sr, CK_NORMAL);
425    fails = srunner_ntests_failed(sr);
426    srunner_free(sr);
427    return fails;
428}
429