1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 * testutil.h 6 * 7 * Utility functions for handling test errors 8 * 9 */ 10 11 #ifndef _TESTUTIL_H 12 #define _TESTUTIL_H 13 14 #include "pkix.h" 15 #include "plstr.h" 16 #include "prprf.h" 17 #include "prlong.h" 18 #include "pkix_pl_common.h" 19 #include "secutil.h" 20 #include <stdio.h> 21 #include <ctype.h> 22 23 #ifdef __cplusplus 24 extern "C" { 25 #endif 26 27 /* 28 * In order to have a consistent format for displaying test information, 29 * all tests are REQUIRED to use the functions provided by this library 30 * (libtestutil.a) for displaying their information. 31 * 32 * A test using this library begins with a call to startTests with the test 33 * name as the arg (which is used only for formatting). Before the first 34 * subtest, a call to subTest should be made with the subtest name as the arg 35 * (again, for formatting). If the subTest is successful, then no action 36 * is needed. However, if the subTest is not successful, then a call 37 * to testError should be made with a descriptive error message as the arg. 38 * Note that a subTest MUST NOT call testError more than once. 39 * Finally, a call to endTests is made with the test name as the arg (for 40 * formatting). Note that most of these macros assume that a variable named 41 * "plContext" of type (void *) has been defined by the test. As such, it 42 * is essential that the test satisfy this condition. 43 */ 44 45 /* 46 * PKIX_TEST_STD_VARS should be called at the beginning of every function 47 * that uses PKIX_TEST_RETURN (e.g. subTests), but it should be called only 48 * AFTER declaring local variables (so we don't get compiler warnings about 49 * declarations after statements). PKIX_TEST_STD_VARS declares and initializes 50 * several variables needed by the other test macros. 51 */ 52 #define PKIX_TEST_STD_VARS() \ 53 PKIX_Error *pkixTestErrorResult = NULL; \ 54 char *pkixTestErrorMsg = NULL; 55 56 /* 57 * PKIX_TEST_EXPECT_NO_ERROR should be used to wrap a standard PKIX function 58 * call (one which returns a pointer to PKIX_Error) that is expected to return 59 * NULL (i.e. to succeed). If "pkixTestErrorResult" is not NULL, 60 * "goto cleanup" is executed, where a testError call is made if there were 61 * unexpected results. This macro MUST NOT be called after the "cleanup" label. 62 * 63 * Example Usage: PKIX_TEST_EXPECT_NO_ERROR(pkixFunc_expected_to_succeed(...)); 64 */ 65 66 #define PKIX_TEST_EXPECT_NO_ERROR(func) \ 67 do { \ 68 pkixTestErrorResult = (func); \ 69 if (pkixTestErrorResult) { \ 70 goto cleanup; \ 71 } \ 72 } while (0) 73 74 /* 75 * PKIX_TEST_EXPECT_ERROR should be used to wrap a standard PKIX function call 76 * (one which returns a pointer to PKIX_Error) that is expected to return 77 * a non-NULL value (i.e. to fail). If "pkixTestErrorResult" is NULL, 78 * "pkixTestErrorMsg" is set to a standard string and "goto cleanup" 79 * is executed, where a testError call is made if there were unexpected 80 * results. This macro MUST NOT be called after the "cleanup" label. 81 * 82 * Example Usage: PKIX_TEST_EXPECT_ERROR(pkixFunc_expected_to_fail(...)); 83 */ 84 85 #define PKIX_TEST_EXPECT_ERROR(func) \ 86 do { \ 87 pkixTestErrorResult = (func); \ 88 if (!pkixTestErrorResult) { \ 89 pkixTestErrorMsg = \ 90 "Should have thrown an error here."; \ 91 goto cleanup; \ 92 } \ 93 PKIX_TEST_DECREF_BC(pkixTestErrorResult); \ 94 } while (0) 95 96 /* 97 * PKIX_TEST_DECREF_BC is a convenience macro which should only be called 98 * BEFORE the "cleanup" label ("BC"). If the input parameter is non-NULL, it 99 * DecRefs the input parameter and wraps the function with 100 * PKIX_TEST_EXPECT_NO_ERROR, which executes "goto cleanup" upon error. 101 * This macro MUST NOT be called after the "cleanup" label. 102 */ 103 104 #define PKIX_TEST_DECREF_BC(obj) \ 105 do { \ 106 if (obj) { \ 107 PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_DecRef((PKIX_PL_Object *)(obj), plContext)); \ 108 obj = NULL; \ 109 } \ 110 } while (0) 111 112 /* 113 * PKIX_TEST_DECREF_AC is a convenience macro which should only be called 114 * AFTER the "cleanup" label ("AC"). If the input parameter is non-NULL, it 115 * DecRefs the input parameter. A pkixTestTempResult variable is used to prevent 116 * incorrectly overwriting pkixTestErrorResult with NULL. 117 * In the case DecRef succeeds, pkixTestTempResult will be NULL, and we won't 118 * overwrite a previously set pkixTestErrorResult (if any). If DecRef fails, 119 * then we do want to overwrite a previously set pkixTestErrorResult since a 120 * DecRef failure is fatal and may be indicative of memory corruption. 121 */ 122 123 #define PKIX_TEST_DECREF_AC(obj) \ 124 do { \ 125 if (obj) { \ 126 PKIX_Error *pkixTestTempResult = NULL; \ 127 pkixTestTempResult = \ 128 PKIX_PL_Object_DecRef((PKIX_PL_Object *)(obj), plContext); \ 129 if (pkixTestTempResult) \ 130 pkixTestErrorResult = pkixTestTempResult; \ 131 obj = NULL; \ 132 } \ 133 } while (0) 134 135 /* 136 * PKIX_TEST_RETURN must always be AFTER the "cleanup" label. It does nothing 137 * if everything went as expected. However, if there were unexpected results, 138 * PKIX_TEST_RETURN calls testError, which displays a standard failure message 139 * and increments the number of subtests that have failed. In the case 140 * of an unexpected error, testError is called using the error's description 141 * as an input and the error is DecRef'd. In the case of unexpected success 142 * testError is called with a standard string. 143 */ 144 #define PKIX_TEST_RETURN() \ 145 { \ 146 if (pkixTestErrorMsg) { \ 147 testError(pkixTestErrorMsg); \ 148 } else if (pkixTestErrorResult) { \ 149 pkixTestErrorMsg = \ 150 PKIX_Error2ASCII(pkixTestErrorResult, plContext); \ 151 if (pkixTestErrorMsg) { \ 152 testError(pkixTestErrorMsg); \ 153 PKIX_PL_Free((PKIX_PL_Object *)pkixTestErrorMsg, \ 154 plContext); \ 155 } else { \ 156 testError("PKIX_Error2ASCII Failed"); \ 157 } \ 158 if (pkixTestErrorResult != PKIX_ALLOC_ERROR()) { \ 159 PKIX_PL_Object_DecRef((PKIX_PL_Object *)pkixTestErrorResult, \ 160 plContext); \ 161 pkixTestErrorResult = NULL; \ 162 } \ 163 } \ 164 } 165 166 /* 167 * PKIX_TEST_EQ_HASH_TOSTR_DUP is a convenience macro which executes the 168 * standard set of operations that test the Equals, Hashcode, ToString, and 169 * Duplicate functions of an object type. The goodObj, equalObj, and diffObj 170 * are as the names suggest. The expAscii parameter is the expected result of 171 * calling ToString on the goodObj. If expAscii is NULL, then ToString will 172 * not be called on the goodObj. The checkDuplicate parameter is treated as 173 * a Boolean to indicate whether the Duplicate function should be tested. If 174 * checkDuplicate is NULL, then Duplicate will not be called on the goodObj. 175 * The type is the name of the function's family. For example, if the type is 176 * Cert, this macro will call PKIX_PL_Cert_Equals, PKIX_PL_Cert_Hashcode, and 177 * PKIX_PL_Cert_ToString. 178 * 179 * Note: If goodObj uses the default Equals and Hashcode functions, then 180 * for goodObj and equalObj to be equal, they must have the same pointer value. 181 */ 182 #define PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObj, equalObj, diffObj, \ 183 expAscii, type, checkDuplicate) \ 184 do { \ 185 subTest("PKIX_PL_" #type "_Equals <match>"); \ 186 testEqualsHelper((PKIX_PL_Object *)(goodObj), \ 187 (PKIX_PL_Object *)(equalObj), \ 188 PKIX_TRUE, \ 189 plContext); \ 190 subTest("PKIX_PL_" #type "_Hashcode <match>"); \ 191 testHashcodeHelper((PKIX_PL_Object *)(goodObj), \ 192 (PKIX_PL_Object *)(equalObj), \ 193 PKIX_TRUE, \ 194 plContext); \ 195 subTest("PKIX_PL_" #type "_Equals <non-match>"); \ 196 testEqualsHelper((PKIX_PL_Object *)(goodObj), \ 197 (PKIX_PL_Object *)(diffObj), \ 198 PKIX_FALSE, \ 199 plContext); \ 200 subTest("PKIX_PL_" #type "_Hashcode <non-match>"); \ 201 testHashcodeHelper((PKIX_PL_Object *)(goodObj), \ 202 (PKIX_PL_Object *)(diffObj), \ 203 PKIX_FALSE, \ 204 plContext); \ 205 if (expAscii) { \ 206 subTest("PKIX_PL_" #type "_ToString"); \ 207 testToStringHelper((PKIX_PL_Object *)(goodObj), \ 208 (expAscii), \ 209 plContext); \ 210 } \ 211 if (checkDuplicate) { \ 212 subTest("PKIX_PL_" #type "_Duplicate"); \ 213 testDuplicateHelper((PKIX_PL_Object *)goodObj, plContext); \ 214 } \ 215 } while (0) 216 217 /* 218 * PKIX_TEST_DECREF_BC is a convenience macro which should only be called 219 * BEFORE the "cleanup" label ("BC"). If the input parameter is non-NULL, it 220 * DecRefs the input parameter and wraps the function with 221 * PKIX_TEST_EXPECT_NO_ERROR, which executes "goto cleanup" upon error. 222 * This macro MUST NOT be called after the "cleanup" label. 223 */ 224 225 #define PKIX_TEST_ABORT_ON_NULL(obj) \ 226 do { \ 227 if (!obj) { \ 228 goto cleanup; \ 229 } \ 230 } while (0) 231 232 #define PKIX_TEST_ARENAS_ARG(arena) \ 233 (arena ? (PORT_Strcmp(arena, "arenas") ? PKIX_FALSE : (j++, PKIX_TRUE)) : PKIX_FALSE) 234 235 #define PKIX_TEST_ERROR_RECEIVED (pkixTestErrorMsg || pkixTestErrorResult) 236 237 /* see source file for function documentation */ 238 239 void startTests(char *testName); 240 241 void endTests(char *testName); 242 243 void subTest(char *subTestName); 244 245 void testError(char *msg); 246 247 extern PKIX_Error * 248 _ErrorCheck(PKIX_Error *errorResult); 249 250 extern PKIX_Error * 251 _OutputError(PKIX_Error *errorResult); 252 253 char *PKIX_String2ASCII(PKIX_PL_String *string, void *plContext); 254 255 char *PKIX_Error2ASCII(PKIX_Error *error, void *plContext); 256 257 char *PKIX_Object2ASCII(PKIX_PL_Object *object); 258 259 char *PKIX_Cert2ASCII(PKIX_PL_Cert *cert); 260 261 void 262 testHashcodeHelper( 263 PKIX_PL_Object *goodObject, 264 PKIX_PL_Object *otherObject, 265 PKIX_Boolean match, 266 void *plContext); 267 268 void 269 testToStringHelper( 270 PKIX_PL_Object *goodObject, 271 char *expected, 272 void *plContext); 273 274 void 275 testEqualsHelper( 276 PKIX_PL_Object *goodObject, 277 PKIX_PL_Object *otherObject, 278 PKIX_Boolean match, 279 void *plContext); 280 281 void 282 testDuplicateHelper( 283 PKIX_PL_Object *object, 284 void *plContext); 285 void 286 testErrorUndo(char *msg); 287 288 #ifdef __cplusplus 289 } 290 #endif 291 292 #endif /* TESTUTIL_H */ 293