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 // Function definitions
39 START_TEST (check_base64
) {
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
49 "VGhpcyBpcyBhIHN0cmluZw==", // 24
50 "TWF5YmUgdXBvbiBhIHRpbWU=", // 24
51 "QW5kIHRoZW4gdGhlcmUgd2Fz", // 24
52 "SW4gdGhlIGVuZCB0aGVyZSBpcw==", // 24
58 for (pos
= 0; pos
< 4; ++pos
) {
60 size
= base64_encode_size(strlen(string
[pos
]));
62 ck_assert(size
== (strlen(base64
[pos
]) + 1));
63 output
= calloc(sizeof(char), size
);
65 base64_encode_binary_to_base64((unsigned char *)string
[pos
], strlen(string
[pos
]), (unsigned char *)output
, &size
);
67 ck_assert(size
== (strlen(base64
[pos
]) + 1));
68 ck_assert_str_eq(output
, base64
[pos
]);
71 size
= base64_decode_size(strlen(base64
[pos
]));
73 ck_assert(size
>= (strlen(string
[pos
]) + 1));
74 ck_assert(size
< (strlen(string
[pos
]) + 4));
75 output
= calloc(sizeof(char), size
+ 1);
77 base64_decode_base64_to_binary((unsigned char *)base64
[pos
], strlen(base64
[pos
]), (unsigned char *)output
, &size
);
79 ck_assert(size
>= (strlen(string
[pos
]) + 1));
80 ck_assert(size
< (strlen(string
[pos
]) + 4));
81 ck_assert_str_eq(output
, string
[pos
]);
86 START_TEST (check_contrac
) {
88 unsigned char const *tk
;
91 // Generate some keys, check the results
94 contrac
= contrac_new();
95 ck_assert(contrac
!= NULL
);
97 result
= contrac_get_initialised(contrac
);
98 ck_assert(result
== false);
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);
106 result
= contrac_generate_tracing_key(contrac
);
107 ck_assert(result
== true);
109 result
= contrac_get_initialised(contrac
);
110 ck_assert(result
== false);
112 // The random generator could generate all zeros, but we'll take the risk
113 tk
= contrac_get_tracing_key(contrac
);
115 for (pos
= 0; pos
< TK_SIZE
; ++pos
) {
120 ck_assert(result
== true);
122 result
= contrac_get_initialised(contrac
);
123 ck_assert(result
== false);
125 result
= contrac_set_day_number(contrac
, 23);
126 ck_assert(result
== true);
128 result
= contrac_get_initialised(contrac
);
129 ck_assert(result
== false);
131 result
= contrac_set_time_interval_number(contrac
, 76);
132 ck_assert(result
== true);
134 result
= contrac_get_initialised(contrac
);
135 ck_assert(result
== true);
138 contrac_delete(contrac
);
142 START_TEST (check_dtk
) {
144 char const *tracing_key_base64
= "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=";
145 char tk_base64
[TK_SIZE_BASE64
+ 1];
146 char dtk_base64
[DTK_SIZE_BASE64
+ 1];
148 // Generate some keys, check the results
151 contrac
= contrac_new();
152 ck_assert(contrac
!= NULL
);
154 contrac_set_tracing_key_base64(contrac
, tracing_key_base64
);
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
);
160 // Check the Daily Tracing Keys are generated correctly
161 // Should use the standard test vectors when they're available
163 result
= contrac_set_day_number(contrac
, 12);
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==");
170 result
= contrac_set_day_number(contrac
, 0);
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==");
176 result
= contrac_set_day_number(contrac
, 143);
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==");
183 contrac_delete(contrac
);
187 START_TEST (check_rpi
) {
189 char const *tracing_key_base64
[2] = {
190 "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=",
191 "U3CgpSjF0qFW8DNSTHVWF99few5FOW7RV7kA9j6LFTc=",
193 char rpi_base64
[RPI_SIZE_BASE64
+ 1];
195 // Generate some keys, check the results
198 contrac
= contrac_new();
199 ck_assert(contrac
!= NULL
);
201 contrac_set_tracing_key_base64(contrac
, tracing_key_base64
[0]);
203 result
= contrac_set_day_number(contrac
, 9);
206 // Check the Rolling Proximity Identifiers are generated correctly
207 // Should use the standard test vectors when they're available
209 result
= contrac_set_time_interval_number(contrac
, 0);
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==");
215 result
= contrac_set_time_interval_number(contrac
, 82);
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==");
221 result
= contrac_set_time_interval_number(contrac
, 143);
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==");
227 contrac_set_tracing_key_base64(contrac
, tracing_key_base64
[1]);
229 result
= contrac_set_day_number(contrac
, 500);
232 result
= contrac_set_time_interval_number(contrac
, 1);
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==");
238 result
= contrac_set_time_interval_number(contrac
, 27);
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==");
244 result
= contrac_set_time_interval_number(contrac
, 143);
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==");
251 contrac_delete(contrac
);
255 START_TEST (check_match
) {
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};
269 const unsigned char * rpi_bytes
;
270 const unsigned char * dtk_bytes
;
274 MatchListItem
const * match
;
276 // Generate some keys, check the results
279 contrac
= contrac_new();
280 ck_assert(contrac
!= NULL
);
282 contrac_set_tracing_key_base64(contrac
, tracing_key_base64
);
284 // Generate some beacons (as if collected over BlueTooth)
286 beacon_list
= rpi_list_new();
288 for (pos
= 0; pos
< 8; ++pos
) {
289 result
= contrac_set_day_number(contrac
, beacon_days
[pos
]);
292 result
= contrac_set_time_interval_number(contrac
, beacon_times
[pos
]);
295 rpi_bytes
= contrac_get_proximity_id(contrac
);
297 rpi_assign(rpi
, rpi_bytes
, beacon_times
[pos
]);
299 rpi_list_append(beacon_list
, rpi
);
302 // Generate some diagnosis data (as if provided by a diagnosis server)
304 diagnosis_list
= dtk_list_new();
305 for (pos
= 0; pos
< 2; ++pos
) {
306 result
= contrac_set_day_number(contrac
, diagnosis_days
[pos
]);
309 dtk_bytes
= contrac_get_daily_key(contrac
);
311 dtk_assign(dtk
, dtk_bytes
, diagnosis_days
[pos
]);
313 dtk_list_append(diagnosis_list
, dtk
);
316 // Check that the matching algorithm identifies the beacons that match
318 matches
= match_list_new();
319 match_list_find_matches(matches
, beacon_list
, diagnosis_list
);
321 match
= match_list_first(matches
);
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
])) {
333 match
= match_list_next(match
);
335 ck_assert_int_eq(match_list_count(matches
), 4);
338 match_list_delete(matches
);
339 rpi_list_delete(beacon_list
);
340 dtk_list_delete(diagnosis_list
);
341 contrac_delete(contrac
);
351 s
= suite_create("libcontrac");
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
);
362 srunner_run_all(sr
, CK_NORMAL
);
363 failed
= srunner_ntests_failed(sr
);
366 return (failed
== 0) ? 0 : -1;