b697a94495a105f8a69603644b37b5217ed988ba
[libcontrac.git] / tests / test_contrac.c
1 /** \ingroup contrac
2 * @file
3 * @author David Llewellyn-Jones
4 * @version $(VERSION)
5 *
6 * @section LICENSE
7 *
8 *
9 *
10 * @brief
11 * @section DESCRIPTION
12 *
13 *
14 *
15 */
16
17 // Includes
18
19 #include <check.h>
20 #include <malloc.h>
21
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"
30
31 // Defines
32
33 // Structures
34
35 // Function prototypes
36
37 // Function definitions
38
39 START_TEST (check_base64) {
40 //bool result;
41 //int pos;
42 char *string[4] = {
43 "This is a string", // 16
44 "Maybe upon a time", // 17
45 "And then there was", // 18
46 "In the end there is", // 19
47 };
48 char *base64[4] = {
49 "VGhpcyBpcyBhIHN0cmluZw==", // 24
50 "TWF5YmUgdXBvbiBhIHRpbWU=", // 24
51 "QW5kIHRoZW4gdGhlcmUgd2Fz", // 24
52 "SW4gdGhlIGVuZCB0aGVyZSBpcw==", // 24
53 };
54 size_t size;
55 char * output;
56 int pos;
57
58 for (pos = 0; pos < 4; ++pos) {
59 // Encode
60 size = base64_encode_size(strlen(string[pos]));
61
62 ck_assert(size == (strlen(base64[pos]) + 1));
63 output = calloc(sizeof(char), size);
64
65 base64_encode_binary_to_base64((unsigned char *)string[pos], strlen(string[pos]), (unsigned char *)output, &size);
66
67 ck_assert(size == (strlen(base64[pos]) + 1));
68 ck_assert_str_eq(output, base64[pos]);
69
70 // Decode
71 size = base64_decode_size(strlen(base64[pos]));
72
73 ck_assert(size >= (strlen(string[pos]) + 1));
74 ck_assert(size < (strlen(string[pos]) + 4));
75 output = calloc(sizeof(char), size + 1);
76
77 base64_decode_base64_to_binary((unsigned char *)base64[pos], strlen(base64[pos]), (unsigned char *)output, &size);
78
79 ck_assert(size >= (strlen(string[pos]) + 1));
80 ck_assert(size < (strlen(string[pos]) + 4));
81 ck_assert_str_eq(output, string[pos]);
82 }
83 }
84 END_TEST
85
86 START_TEST (check_contrac) {
87 bool result;
88 unsigned char const *tk;
89 int pos;
90
91 // Generate some keys, check the results
92 Contrac * contrac;
93
94 contrac = contrac_new();
95 ck_assert(contrac != NULL);
96
97 result = contrac_get_initialised(contrac);
98 ck_assert(result == false);
99
100 tk = contrac_get_tracing_key(contrac);
101 // The tracing key will initialise to zero by default
102 for (pos = 0; pos < TK_SIZE; ++pos) {
103 ck_assert(tk[pos] == 0);
104 }
105
106 result = contrac_generate_tracing_key(contrac);
107 ck_assert(result == true);
108
109 result = contrac_get_initialised(contrac);
110 ck_assert(result == false);
111
112 // The random generator could generate all zeros, but we'll take the risk
113 tk = contrac_get_tracing_key(contrac);
114 result = false;
115 for (pos = 0; pos < TK_SIZE; ++pos) {
116 if (tk[pos] != 0) {
117 result = true;
118 }
119 }
120 ck_assert(result == true);
121
122 result = contrac_get_initialised(contrac);
123 ck_assert(result == false);
124
125 result = contrac_set_day_number(contrac, 23);
126 ck_assert(result == true);
127
128 result = contrac_get_initialised(contrac);
129 ck_assert(result == false);
130
131 result = contrac_set_time_interval_number(contrac, 76);
132 ck_assert(result == true);
133
134 result = contrac_get_initialised(contrac);
135 ck_assert(result == true);
136
137 // Clean up
138 contrac_delete(contrac);
139 }
140 END_TEST
141
142 START_TEST (check_dtk) {
143 bool result;
144 char const *tracing_key_base64 = "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=";
145 char tk_base64[TK_SIZE_BASE64 + 1];
146 char dtk_base64[DTK_SIZE_BASE64 + 1];
147
148 // Generate some keys, check the results
149 Contrac * contrac;
150
151 contrac = contrac_new();
152 ck_assert(contrac != NULL);
153
154 contrac_set_tracing_key_base64(contrac, tracing_key_base64);
155
156 contrac_get_tracing_key_base64(contrac, tk_base64);
157 ck_assert_int_eq(strlen(tk_base64), TK_SIZE_BASE64);
158 ck_assert_str_eq(tracing_key_base64, tk_base64);
159
160 // Check the Daily Tracing Keys are generated correctly
161 // Should use the standard test vectors when they're available
162
163 result = contrac_set_day_number(contrac, 12);
164 ck_assert(result);
165 contrac_get_daily_key_base64(contrac, dtk_base64);
166 ck_assert_int_eq(strlen(dtk_base64), DTK_SIZE_BASE64);
167 ck_assert_str_eq(dtk_base64, "AzZ389DsGecAjZqby1sLNQ==");
168
169
170 result = contrac_set_day_number(contrac, 0);
171 ck_assert(result);
172 contrac_get_daily_key_base64(contrac, dtk_base64);
173 ck_assert_int_eq(strlen(dtk_base64), DTK_SIZE_BASE64);
174 ck_assert_str_eq(dtk_base64, "p7LrsTReTw3k721eIWDjRw==");
175
176 result = contrac_set_day_number(contrac, 143);
177 ck_assert(result);
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, "f6RZL/2wGCzxSBzZc9xVNQ==");
181
182 // Clean up
183 contrac_delete(contrac);
184 }
185 END_TEST
186
187 START_TEST (check_rpi) {
188 bool result;
189 char const *tracing_key_base64[2] = {
190 "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=",
191 "U3CgpSjF0qFW8DNSTHVWF99few5FOW7RV7kA9j6LFTc=",
192 };
193 char rpi_base64[RPI_SIZE_BASE64 + 1];
194
195 // Generate some keys, check the results
196 Contrac * contrac;
197
198 contrac = contrac_new();
199 ck_assert(contrac != NULL);
200
201 contrac_set_tracing_key_base64(contrac, tracing_key_base64[0]);
202
203 result = contrac_set_day_number(contrac, 9);
204 ck_assert(result);
205
206 // Check the Rolling Proximity Identifiers are generated correctly
207 // Should use the standard test vectors when they're available
208
209 result = contrac_set_time_interval_number(contrac, 0);
210 ck_assert(result);
211 contrac_get_proximity_id_base64(contrac, rpi_base64);
212 ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64);
213 ck_assert_str_eq(rpi_base64, "++ucH9hoIkGwCzM+J09faQ==");
214
215 result = contrac_set_time_interval_number(contrac, 82);
216 ck_assert(result);
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, "GrqeroryZQ+Uvhx10zfKWw==");
220
221 result = contrac_set_time_interval_number(contrac, 143);
222 ck_assert(result);
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, "+9eL1UlYZ9buUCFF5qRDUA==");
226
227 contrac_set_tracing_key_base64(contrac, tracing_key_base64[1]);
228
229 result = contrac_set_day_number(contrac, 500);
230 ck_assert(result);
231
232 result = contrac_set_time_interval_number(contrac, 1);
233 ck_assert(result);
234 contrac_get_proximity_id_base64(contrac, rpi_base64);
235 ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64);
236 ck_assert_str_eq(rpi_base64, "XmePWi0HlgHyBcVUb0KhjQ==");
237
238 result = contrac_set_time_interval_number(contrac, 27);
239 ck_assert(result);
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, "LlPznz6D044ZKYsY3sHJew==");
243
244 result = contrac_set_time_interval_number(contrac, 143);
245 ck_assert(result);
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, "QDG50cy9NTXZ3zDAUGkePQ==");
249
250 // Clean up
251 contrac_delete(contrac);
252 }
253 END_TEST
254
255 START_TEST (check_match) {
256 bool result;
257 char const *tracing_key_base64 = "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=";
258 RpiList * beacon_list;
259 DtkList * diagnosis_list;
260 // There are four matches in amongst this lot
261 // (day, time) = (12, 15), (1175, 142), (1175, 67), (12, 93)
262 uint32_t beacon_days[8] = {55, 12, 0, 8787, 1175, 1175, 187, 12};
263 uint8_t beacon_times[8] = {1, 15, 5, 101, 142, 67, 51, 93};
264 uint32_t diagnosis_days[2] = {1175, 12};
265 // Summarise the four matches
266 uint32_t match_days[4] = {12, 1175, 1175, 12};
267 uint8_t match_times[4] = {15, 142, 67, 93};
268 int pos;
269 const unsigned char * rpi_bytes;
270 const unsigned char * dtk_bytes;
271 Rpi * rpi;
272 Dtk * dtk;
273 MatchList * matches;
274 MatchListItem const * match;
275
276 // Generate some keys, check the results
277 Contrac * contrac;
278
279 contrac = contrac_new();
280 ck_assert(contrac != NULL);
281
282 contrac_set_tracing_key_base64(contrac, tracing_key_base64);
283
284 // Generate some beacons (as if collected over BlueTooth)
285
286 beacon_list = rpi_list_new();
287
288 for (pos = 0; pos < 8; ++pos) {
289 result = contrac_set_day_number(contrac, beacon_days[pos]);
290 ck_assert(result);
291
292 result = contrac_set_time_interval_number(contrac, beacon_times[pos]);
293 ck_assert(result);
294
295 rpi_bytes = contrac_get_proximity_id(contrac);
296 rpi = rpi_new();
297 rpi_assign(rpi, rpi_bytes, beacon_times[pos]);
298
299 rpi_list_append(beacon_list, rpi);
300 }
301
302 // Generate some diagnosis data (as if provided by a diagnosis server)
303
304 diagnosis_list = dtk_list_new();
305 for (pos = 0; pos < 2; ++pos) {
306 result = contrac_set_day_number(contrac, diagnosis_days[pos]);
307 ck_assert(result);
308
309 dtk_bytes = contrac_get_daily_key(contrac);
310 dtk = dtk_new();
311 dtk_assign(dtk, dtk_bytes, diagnosis_days[pos]);
312
313 dtk_list_append(diagnosis_list, dtk);
314 }
315
316 // Check that the matching algorithm identifies the beacons that match
317
318 matches = match_list_new();
319 match_list_find_matches(matches, beacon_list, diagnosis_list);
320
321 match = match_list_first(matches);
322
323 while (match) {
324 result = false;
325 for (pos = 0; pos < 4; ++pos) {
326 if ((match_list_get_day_number(match) == match_days[pos]) && (match_list_get_time_interval_number(match) == match_times[pos])) {
327 result = true;
328 }
329 }
330
331 ck_assert(result);
332
333 match = match_list_next(match);
334 }
335 ck_assert_int_eq(match_list_count(matches), 4);
336
337 // Clean up
338 match_list_delete(matches);
339 rpi_list_delete(beacon_list);
340 dtk_list_delete(diagnosis_list);
341 contrac_delete(contrac);
342 }
343 END_TEST
344
345 int main(void) {
346 int failed;
347 Suite * s;
348 SRunner *sr;
349 TCase * tc;
350
351 s = suite_create("libcontrac");
352
353 tc = tcase_create("Contrac");
354 tcase_add_test(tc, check_base64);
355 tcase_add_test(tc, check_contrac);
356 tcase_add_test(tc, check_dtk);
357 tcase_add_test(tc, check_rpi);
358 tcase_add_test(tc, check_match);
359 suite_add_tcase(s, tc);
360 sr = srunner_create(s);
361
362 srunner_run_all(sr, CK_NORMAL);
363 failed = srunner_ntests_failed(sr);
364 srunner_free(sr);
365
366 return (failed == 0) ? 0 : -1;
367 }
368