1 /*==============================================================================
2 run_tests.c -- test aggregator and results reporting
3
4 Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
5
6 SPDX-License-Identifier: BSD-3-Clause
7
8 See BSD-3-Clause license in README.md
9
10 Created on 9/30/18
11 =============================================================================*/
12
13 #include "run_tests.h"
14 #include "UsefulBuf.h"
15 #include <stdbool.h>
16 #include <stddef.h>
17
18 #include "t_cose_test.h"
19 #include "t_cose_sign_verify_test.h"
20
21
22 /*
23 Test configuration
24 */
25
26 typedef int_fast32_t (test_fun_t)(void);
27 typedef const char * (test_fun2_t)(void);
28
29
30 #define TEST_ENTRY(test_name) {#test_name, test_name, true}
31 #define TEST_ENTRY_DISABLED(test_name) {#test_name, test_name, false}
32
33 typedef struct {
34 const char *szTestName;
35 test_fun_t *test_fun;
36 bool bEnabled;
37 } test_entry;
38
39 #ifdef STRING_RETURNING_TESTS
40 typedef struct {
41 const char *szTestName;
42 test_fun2_t *test_fun;
43 bool bEnabled;
44 } test_entry2;
45
46
47 static test_entry2 s_tests2[] = {
48 };
49 #endif
50
51 static test_entry s_tests[] = {
52 TEST_ENTRY(sign1_structure_decode_test),
53 TEST_ENTRY(crit_parameters_test),
54 TEST_ENTRY(bad_parameters_test),
55
56 #ifndef T_COSE_DISABLE_SIGN_VERIFY_TESTS
57 /* Many tests can be run without a crypto library integration and
58 * provide good test coverage of everything but the signing and
59 * verification. These tests can't be run with signing and
60 * verification short circuited. They must have a real crypto
61 * library integrated. */
62 TEST_ENTRY(sign_verify_basic_test),
63 TEST_ENTRY(sign_verify_make_cwt_test),
64 TEST_ENTRY(sign_verify_sig_fail_test),
65 TEST_ENTRY(sign_verify_get_size_test),
66 #endif /* T_COSE_DISABLE_SIGN_VERIFY_TESTS */
67
68 #ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
69 /* These tests can't run if short-circuit signatures are disabled.
70 * The most critical ones are replicated in the group of tests
71 * that require a real crypto library. Typically short-circuit
72 * signing is only disabled for extreme code size savings so these
73 * tests are typically always run.
74 */
75 TEST_ENTRY(content_type_test),
76 TEST_ENTRY(all_header_parameters_test),
77 TEST_ENTRY(cose_example_test),
78 TEST_ENTRY(short_circuit_signing_error_conditions_test),
79 TEST_ENTRY(short_circuit_self_test),
80 TEST_ENTRY(short_circuit_decode_only_test),
81 TEST_ENTRY(short_circuit_make_cwt_test),
82 TEST_ENTRY(short_circuit_verify_fail_test),
83 #endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
84
85 #ifdef T_COSE_ENABLE_HASH_FAIL_TEST
86 TEST_ENTRY(short_circuit_hash_fail_test),
87 #endif /* T_COSE_DISABLE_HASH_FAIL_TEST */
88 };
89
90
91
92 /**
93 \brief Convert number to ASCII string, similar to sprint
94
95 \param [in] nNum The 32-bit integer to convert.
96 \param [in] StringMem The buffer to output to.
97
98 \return POinter to NULL-terminated string with result or "XXX" on failure.
99
100 Convert a number up to 999999999 to a string. This is so sprintf doesn't
101 have to be linked in so as to minimized dependencies even in test code.
102
103 StringMem should be 12 bytes long, 9 for digits, 1 for minus and
104 1 for \0 termination.
105 */
NumToString(int32_t nNum,UsefulBuf StringMem)106 static const char *NumToString(int32_t nNum, UsefulBuf StringMem)
107 {
108 const int32_t nMax = 1000000000;
109
110 UsefulOutBuf OutBuf;
111 UsefulOutBuf_Init(&OutBuf, StringMem);
112
113 if(nNum < 0) {
114 UsefulOutBuf_AppendByte(&OutBuf, '-');
115 nNum = -nNum;
116 }
117 if(nNum > nMax-1) {
118 return "XXX";
119 }
120
121 bool bDidSomeOutput = false;
122 for(int32_t n = nMax; n > 0; n/=10) {
123 int32_t nDigitValue = nNum/n;
124 if(nDigitValue || bDidSomeOutput){
125 bDidSomeOutput = true;
126 UsefulOutBuf_AppendByte(&OutBuf, (uint8_t)('0' + nDigitValue));
127 nNum -= nDigitValue * n;
128 }
129 }
130 if(!bDidSomeOutput){
131 UsefulOutBuf_AppendByte(&OutBuf, '0');
132 }
133 UsefulOutBuf_AppendByte(&OutBuf, '\0');
134
135 return UsefulOutBuf_GetError(&OutBuf) ? "" : StringMem.ptr;
136 }
137
138
139 /*
140 Public function. See run_test.h.
141 */
RunTestsTCose(const char * szTestNames[],OutputStringCB pfOutput,void * poutCtx,int * pNumTestsRun)142 int RunTestsTCose(const char *szTestNames[],
143 OutputStringCB pfOutput,
144 void *poutCtx,
145 int *pNumTestsRun)
146 {
147 // int (-32767 to 32767 according to C standard) used by conscious choice
148 int nTestsFailed = 0;
149 int nTestsRun = 0;
150 UsefulBuf_MAKE_STACK_UB(StringStorage, 12);
151
152 #ifdef STRING_RETURNING_TESTS
153
154 test_entry2 *t2;
155 const test_entry2 *s_tests2_end = s_tests2 + sizeof(s_tests2)/sizeof(test_entry2);
156
157 for(t2 = s_tests2; t2 < s_tests2_end; t2++) {
158 if(szTestNames[0]) {
159 // Some tests have been named
160 const char **szRequestedNames;
161 for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) {
162 if(!strcmp(t2->szTestName, *szRequestedNames)) {
163 break; // Name matched
164 }
165 }
166 if(*szRequestedNames == NULL) {
167 // Didn't match this test
168 continue;
169 }
170 } else {
171 // no tests named, but don't run "disabled" tests
172 if(!t2->bEnabled) {
173 // Don't run disabled tests when all tests are being run
174 // as indicated by no specific test names being given
175 continue;
176 }
177 }
178 const char * szTestResult = (t2->test_fun)();
179 nTestsRun++;
180 if(pfOutput) {
181 (*pfOutput)(t2->szTestName, poutCtx, 0);
182 }
183
184 if(szTestResult) {
185 if(pfOutput) {
186 (*pfOutput)(" FAILED (returned ", poutCtx, 0);
187 (*pfOutput)(szTestResult, poutCtx, 0);
188 (*pfOutput)(")", poutCtx, 1);
189 }
190 nTestsFailed++;
191 } else {
192 if(pfOutput) {
193 (*pfOutput)( " PASSED", poutCtx, 1);
194 }
195 }
196 }
197 #endif
198
199
200 test_entry *t;
201 const test_entry *s_tests_end = s_tests + sizeof(s_tests)/sizeof(test_entry);
202
203 for(t = s_tests; t < s_tests_end; t++) {
204 if(szTestNames[0]) {
205 // Some tests have been named
206 const char **szRequestedNames;
207 for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) {
208 if(!strcmp(t->szTestName, *szRequestedNames)) {
209 break; // Name matched
210 }
211 }
212 if(*szRequestedNames == NULL) {
213 // Didn't match this test
214 continue;
215 }
216 } else {
217 // no tests named, but don't run "disabled" tests
218 if(!t->bEnabled) {
219 // Don't run disabled tests when all tests are being run
220 // as indicated by no specific test names being given
221 continue;
222 }
223 }
224
225 int nTestResult = (t->test_fun)();
226 nTestsRun++;
227 if(pfOutput) {
228 (*pfOutput)(t->szTestName, poutCtx, 0);
229 }
230
231 if(nTestResult) {
232 if(pfOutput) {
233 (*pfOutput)(" FAILED (returned ", poutCtx, 0);
234 (*pfOutput)(NumToString(nTestResult, StringStorage), poutCtx, 0);
235 (*pfOutput)(")", poutCtx, 1);
236 }
237 nTestsFailed++;
238 } else {
239 if(pfOutput) {
240 (*pfOutput)( " PASSED", poutCtx, 1);
241 }
242 }
243 }
244
245 if(pNumTestsRun) {
246 *pNumTestsRun = nTestsRun;
247 }
248
249 if(pfOutput) {
250 (*pfOutput)( "SUMMARY: ", poutCtx, 0);
251 (*pfOutput)( NumToString(nTestsRun, StringStorage), poutCtx, 0);
252 (*pfOutput)( " tests run; ", poutCtx, 0);
253 (*pfOutput)( NumToString(nTestsFailed, StringStorage), poutCtx, 0);
254 (*pfOutput)( " tests failed", poutCtx, 1);
255 }
256
257 return nTestsFailed;
258 }
259
260
261 /*
262 Public function. See run_test.h.
263 */
PrintSize(const char * szWhat,uint32_t uSize,OutputStringCB pfOutput,void * pOutCtx)264 static void PrintSize(const char *szWhat,
265 uint32_t uSize,
266 OutputStringCB pfOutput,
267 void *pOutCtx)
268 {
269 UsefulBuf_MAKE_STACK_UB(buffer, 20);
270
271 (*pfOutput)(szWhat, pOutCtx, 0);
272 (*pfOutput)(" ", pOutCtx, 0);
273 (*pfOutput)(NumToString((int32_t)uSize, buffer), pOutCtx, 0);
274 (*pfOutput)("", pOutCtx, 1);
275 }
276
277
278
279
280 #include "t_cose_sign1_sign.h" /* For struct size printing */
281 #include "t_cose_sign1_verify.h" /* For struct size printing */
282 #include "t_cose_crypto.h" /* For struct size printing */
283
284
285 /*
286 Public function. See run_test.h.
287 */
PrintSizesTCose(OutputStringCB pfOutput,void * pOutCtx)288 void PrintSizesTCose(OutputStringCB pfOutput, void *pOutCtx)
289 {
290 // Type and size of return from sizeof() varies. These will never be large
291 // so cast is safe.
292 PrintSize("sizeof(struct t_cose_sign1_ctx)",
293 (uint32_t)sizeof(struct t_cose_sign1_sign_ctx),
294 pfOutput, pOutCtx);
295 PrintSize("sizeof(struct t_cose_signing_key)",
296 (uint32_t)sizeof(struct t_cose_key),
297 pfOutput, pOutCtx);
298 PrintSize("sizeof(struct t_cose_crypto_hash)",
299 (uint32_t)sizeof(struct t_cose_crypto_hash),
300 pfOutput, pOutCtx);
301 PrintSize("sizeof(struct t_cose_parameters)",
302 (uint32_t)sizeof(struct t_cose_parameters),
303 pfOutput, pOutCtx);
304 PrintSize("sizeof(struct t_cose_sign1_verify_ctx)",
305 (uint32_t)sizeof(struct t_cose_sign1_verify_ctx),
306 pfOutput, pOutCtx);
307 (*pfOutput)("", pOutCtx, 1);
308 }
309