65bcc4fc2b6a6c2ff5bbdf4000e8ebd59cc5217f
3 * @author David Llewellyn-Jones
11 * @section DESCRIPTION
22 #include "contrac/contrac.h"
23 #include "contrac/contrac_private.h"
24 #include "contrac/utils.h"
25 #include "contrac/dtk.h"
26 #include "contrac/rpi.h"
27 #include "contrac/dtk_list.h"
28 #include "contrac/rpi_list.h"
29 #include "contrac/match.h"
35 // Function prototypes
37 // Override time function
38 static time_t fake_time
= 0;
39 time_t time(time_t *__timer
) {
43 // Function definitions
45 START_TEST (check_base64
) {
49 "This is a string", // 16
50 "Maybe upon a time", // 17
51 "And then there was", // 18
52 "In the end there is", // 19
55 "VGhpcyBpcyBhIHN0cmluZw==", // 24
56 "TWF5YmUgdXBvbiBhIHRpbWU=", // 24
57 "QW5kIHRoZW4gdGhlcmUgd2Fz", // 24
58 "SW4gdGhlIGVuZCB0aGVyZSBpcw==", // 24
64 for (pos
= 0; pos
< 4; ++pos
) {
66 size
= base64_encode_size(strlen(string
[pos
]));
68 ck_assert(size
== (strlen(base64
[pos
]) + 1));
69 output
= calloc(sizeof(char), size
);
71 base64_encode_binary_to_base64((unsigned char *)string
[pos
], strlen(string
[pos
]), (unsigned char *)output
, &size
);
73 ck_assert(size
== (strlen(base64
[pos
]) + 1));
74 ck_assert_str_eq(output
, base64
[pos
]);
77 size
= base64_decode_size(strlen(base64
[pos
]));
79 ck_assert(size
>= (strlen(string
[pos
]) + 1));
80 ck_assert(size
< (strlen(string
[pos
]) + 4));
81 output
= calloc(sizeof(char), size
+ 1);
83 base64_decode_base64_to_binary((unsigned char *)base64
[pos
], strlen(base64
[pos
]), (unsigned char *)output
, &size
);
85 ck_assert(size
>= (strlen(string
[pos
]) + 1));
86 ck_assert(size
< (strlen(string
[pos
]) + 4));
87 ck_assert_str_eq(output
, string
[pos
]);
92 START_TEST (check_contrac
) {
94 unsigned char const *tk
;
97 // Generate some keys, check the results
100 contrac
= contrac_new();
101 ck_assert(contrac
!= NULL
);
103 result
= contrac_get_initialised(contrac
);
104 ck_assert(result
== false);
106 tk
= contrac_get_tracing_key(contrac
);
107 // The tracing key will initialise to zero by default
108 for (pos
= 0; pos
< TK_SIZE
; ++pos
) {
109 ck_assert(tk
[pos
] == 0);
112 result
= contrac_generate_tracing_key(contrac
);
113 ck_assert(result
== true);
115 result
= contrac_get_initialised(contrac
);
116 ck_assert(result
== false);
118 // The random generator could generate all zeros, but we'll take the risk
119 tk
= contrac_get_tracing_key(contrac
);
121 for (pos
= 0; pos
< TK_SIZE
; ++pos
) {
126 ck_assert(result
== true);
128 result
= contrac_get_initialised(contrac
);
129 ck_assert(result
== false);
131 result
= contrac_set_day_number(contrac
, 23);
132 ck_assert(result
== true);
134 result
= contrac_get_initialised(contrac
);
135 ck_assert(result
== false);
137 result
= contrac_set_time_interval_number(contrac
, 76);
138 ck_assert(result
== true);
140 result
= contrac_get_initialised(contrac
);
141 ck_assert(result
== true);
144 contrac_delete(contrac
);
148 START_TEST (check_dtk
) {
150 char const *tracing_key_base64
= "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=";
151 char tk_base64
[TK_SIZE_BASE64
+ 1];
152 char dtk_base64
[DTK_SIZE_BASE64
+ 1];
154 // Generate some keys, check the results
157 contrac
= contrac_new();
158 ck_assert(contrac
!= NULL
);
160 contrac_set_tracing_key_base64(contrac
, tracing_key_base64
);
162 contrac_get_tracing_key_base64(contrac
, tk_base64
);
163 ck_assert_int_eq(strlen(tk_base64
), TK_SIZE_BASE64
);
164 ck_assert_str_eq(tracing_key_base64
, tk_base64
);
166 // Check the Daily Tracing Keys are generated correctly
167 // Should use the standard test vectors when they're available
169 result
= contrac_set_day_number(contrac
, 12);
171 contrac_get_daily_key_base64(contrac
, dtk_base64
);
172 ck_assert_int_eq(strlen(dtk_base64
), DTK_SIZE_BASE64
);
173 ck_assert_str_eq(dtk_base64
, "AzZ389DsGecAjZqby1sLNQ==");
176 result
= contrac_set_day_number(contrac
, 0);
178 contrac_get_daily_key_base64(contrac
, dtk_base64
);
179 ck_assert_int_eq(strlen(dtk_base64
), DTK_SIZE_BASE64
);
180 ck_assert_str_eq(dtk_base64
, "p7LrsTReTw3k721eIWDjRw==");
182 result
= contrac_set_day_number(contrac
, 143);
184 contrac_get_daily_key_base64(contrac
, dtk_base64
);
185 ck_assert_int_eq(strlen(dtk_base64
), DTK_SIZE_BASE64
);
186 ck_assert_str_eq(dtk_base64
, "f6RZL/2wGCzxSBzZc9xVNQ==");
189 contrac_delete(contrac
);
193 START_TEST (check_rpi
) {
195 char const *tracing_key_base64
[2] = {
196 "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=",
197 "U3CgpSjF0qFW8DNSTHVWF99few5FOW7RV7kA9j6LFTc=",
199 char rpi_base64
[RPI_SIZE_BASE64
+ 1];
201 // Generate some keys, check the results
204 contrac
= contrac_new();
205 ck_assert(contrac
!= NULL
);
207 contrac_set_tracing_key_base64(contrac
, tracing_key_base64
[0]);
209 result
= contrac_set_day_number(contrac
, 9);
212 // Check the Rolling Proximity Identifiers are generated correctly
213 // Should use the standard test vectors when they're available
215 result
= contrac_set_time_interval_number(contrac
, 0);
217 contrac_get_proximity_id_base64(contrac
, rpi_base64
);
218 ck_assert_int_eq(strlen(rpi_base64
), RPI_SIZE_BASE64
);
219 ck_assert_str_eq(rpi_base64
, "yStiu899O+6xvdLiUdrpsA==");
221 result
= contrac_set_time_interval_number(contrac
, 82);
223 contrac_get_proximity_id_base64(contrac
, rpi_base64
);
224 ck_assert_int_eq(strlen(rpi_base64
), RPI_SIZE_BASE64
);
225 ck_assert_str_eq(rpi_base64
, "aFTYIeEUGYKELi8TUUql+Q==");
227 result
= contrac_set_time_interval_number(contrac
, 143);
229 contrac_get_proximity_id_base64(contrac
, rpi_base64
);
230 ck_assert_int_eq(strlen(rpi_base64
), RPI_SIZE_BASE64
);
231 ck_assert_str_eq(rpi_base64
, "MK9mDdgTsgsh6Vxp0XhasA==");
233 contrac_set_tracing_key_base64(contrac
, tracing_key_base64
[1]);
235 result
= contrac_set_day_number(contrac
, 500);
238 result
= contrac_set_time_interval_number(contrac
, 1);
240 contrac_get_proximity_id_base64(contrac
, rpi_base64
);
241 ck_assert_int_eq(strlen(rpi_base64
), RPI_SIZE_BASE64
);
242 ck_assert_str_eq(rpi_base64
, "layNswS/rQxovfYnBhjXJg==");
244 result
= contrac_set_time_interval_number(contrac
, 27);
246 contrac_get_proximity_id_base64(contrac
, rpi_base64
);
247 ck_assert_int_eq(strlen(rpi_base64
), RPI_SIZE_BASE64
);
248 ck_assert_str_eq(rpi_base64
, "BJyzAC3hyVfcWOhQ9paEFA==");
250 result
= contrac_set_time_interval_number(contrac
, 143);
252 contrac_get_proximity_id_base64(contrac
, rpi_base64
);
253 ck_assert_int_eq(strlen(rpi_base64
), RPI_SIZE_BASE64
);
254 ck_assert_str_eq(rpi_base64
, "ItETUQc372fOzJKHvF8z6w==");
257 contrac_delete(contrac
);
261 START_TEST (check_match
) {
263 char const *tracing_key_base64
= "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=";
264 RpiList
* beacon_list
;
265 DtkList
* diagnosis_list
;
266 // There are four matches in amongst this lot
267 // (day, time) = (12, 15), (1175, 142), (1175, 67), (12, 93)
268 uint32_t beacon_days
[8] = {55, 12, 0, 8787, 1175, 1175, 187, 12};
269 uint8_t beacon_times
[8] = {1, 15, 5, 101, 142, 67, 51, 93};
270 uint32_t diagnosis_days
[2] = {1175, 12};
271 // Summarise the four matches
272 uint32_t match_days
[4] = {12, 1175, 1175, 12};
273 uint8_t match_times
[4] = {15, 142, 67, 93};
275 const unsigned char * rpi_bytes
;
276 const unsigned char * dtk_bytes
;
278 MatchListItem
const * match
;
280 // Generate some keys, check the results
283 contrac
= contrac_new();
284 ck_assert(contrac
!= NULL
);
286 contrac_set_tracing_key_base64(contrac
, tracing_key_base64
);
288 // Generate some beacons (as if collected over BlueTooth)
290 beacon_list
= rpi_list_new();
292 for (pos
= 0; pos
< 8; ++pos
) {
293 result
= contrac_set_day_number(contrac
, beacon_days
[pos
]);
296 result
= contrac_set_time_interval_number(contrac
, beacon_times
[pos
]);
299 rpi_bytes
= contrac_get_proximity_id(contrac
);
300 rpi_list_add_beacon(beacon_list
, rpi_bytes
, beacon_times
[pos
]);
303 // Generate some diagnosis data (as if provided by a diagnosis server)
305 diagnosis_list
= dtk_list_new();
306 for (pos
= 0; pos
< 2; ++pos
) {
307 result
= contrac_set_day_number(contrac
, diagnosis_days
[pos
]);
310 dtk_bytes
= contrac_get_daily_key(contrac
);
311 dtk_list_add_diagnosis(diagnosis_list
, dtk_bytes
, diagnosis_days
[pos
]);
314 // Check that the matching algorithm identifies the beacons that match
316 matches
= match_list_new();
317 match_list_find_matches(matches
, beacon_list
, diagnosis_list
);
319 match
= match_list_first(matches
);
323 for (pos
= 0; pos
< 4; ++pos
) {
324 if ((match_list_get_day_number(match
) == match_days
[pos
]) && (match_list_get_time_interval_number(match
) == match_times
[pos
])) {
331 match
= match_list_next(match
);
333 ck_assert_int_eq(match_list_count(matches
), 4);
336 match_list_delete(matches
);
337 rpi_list_delete(beacon_list
);
338 dtk_list_delete(diagnosis_list
);
339 contrac_delete(contrac
);
343 START_TEST (check_time
) {
345 char const *tracing_key_base64
= "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=";
348 time_t base
= 1587415596;
351 char dtk_base64
[DTK_SIZE_BASE64
+ 1];
352 char rpi_base64
[RPI_SIZE_BASE64
+ 1];
355 dn
= epoch_to_day_number(check
);
356 ck_assert_int_eq(dn
, 18372);
357 tn
= epoch_to_time_interval_number(check
);
358 ck_assert_int_eq(tn
, 124);
360 check
= base
+ (24 * 60 * 60);
361 dn
= epoch_to_day_number(check
);
362 ck_assert_int_eq(dn
, 18372 + 1);
363 tn
= epoch_to_time_interval_number(check
);
364 ck_assert_int_eq(tn
, 124);
366 check
= base
- 675 * (24 * 60 * 60);
367 dn
= epoch_to_day_number(check
);
368 ck_assert_int_eq(dn
, 18372 - 675);
369 tn
= epoch_to_time_interval_number(check
);
370 ck_assert_int_eq(tn
, 124);
372 check
= base
+ 15 * (10 * 60);
373 dn
= epoch_to_day_number(check
);
374 ck_assert_int_eq(dn
, 18372);
375 tn
= epoch_to_time_interval_number(check
);
376 ck_assert_int_eq(tn
, 124 + 15);
378 fake_time
= 1587415596;
380 contrac
= contrac_new();
381 contrac_set_tracing_key_base64(contrac
, tracing_key_base64
);
383 contrac_update_current_time(contrac
);
384 result
= contrac_get_initialised(contrac
);
387 contrac_get_daily_key_base64(contrac
, dtk_base64
);
388 ck_assert_str_eq(dtk_base64
, "6GMXmeDAR5XU0AEtZQJ+tA==");
390 contrac_get_proximity_id_base64(contrac
, rpi_base64
);
391 ck_assert_str_eq(rpi_base64
, "ysbjVuF7xf9eDH2y2T8VpQ==");
393 contrac_delete(contrac
);
403 s
= suite_create("libcontrac");
405 tc
= tcase_create("Contrac");
406 tcase_add_test(tc
, check_base64
);
407 tcase_add_test(tc
, check_contrac
);
408 tcase_add_test(tc
, check_dtk
);
409 tcase_add_test(tc
, check_rpi
);
410 tcase_add_test(tc
, check_match
);
411 tcase_add_test(tc
, check_time
);
412 suite_add_tcase(s
, tc
);
413 sr
= srunner_create(s
);
415 srunner_run_all(sr
, CK_NORMAL
);
416 failed
= srunner_ntests_failed(sr
);
419 return (failed
== 0) ? 0 : -1;