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