| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| /* |
| * testutil.h |
| * |
| * Utility functions for handling test errors |
| * |
| */ |
| |
| #ifndef _TESTUTIL_H |
| #define _TESTUTIL_H |
| |
| #include "pkix.h" |
| #include "plstr.h" |
| #include "prprf.h" |
| #include "prlong.h" |
| #include "pkix_pl_common.h" |
| #include "secutil.h" |
| #include <stdio.h> |
| #include <ctype.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* |
| * In order to have a consistent format for displaying test information, |
| * all tests are REQUIRED to use the functions provided by this library |
| * (libtestutil.a) for displaying their information. |
| * |
| * A test using this library begins with a call to startTests with the test |
| * name as the arg (which is used only for formatting). Before the first |
| * subtest, a call to subTest should be made with the subtest name as the arg |
| * (again, for formatting). If the subTest is successful, then no action |
| * is needed. However, if the subTest is not successful, then a call |
| * to testError should be made with a descriptive error message as the arg. |
| * Note that a subTest MUST NOT call testError more than once. |
| * Finally, a call to endTests is made with the test name as the arg (for |
| * formatting). Note that most of these macros assume that a variable named |
| * "plContext" of type (void *) has been defined by the test. As such, it |
| * is essential that the test satisfy this condition. |
| */ |
| |
| /* |
| * PKIX_TEST_STD_VARS should be called at the beginning of every function |
| * that uses PKIX_TEST_RETURN (e.g. subTests), but it should be called only |
| * AFTER declaring local variables (so we don't get compiler warnings about |
| * declarations after statements). PKIX_TEST_STD_VARS declares and initializes |
| * several variables needed by the other test macros. |
| */ |
| #define PKIX_TEST_STD_VARS() \ |
| PKIX_Error *pkixTestErrorResult = NULL; \ |
| char *pkixTestErrorMsg = NULL; |
| |
| /* |
| * PKIX_TEST_EXPECT_NO_ERROR should be used to wrap a standard PKIX function |
| * call (one which returns a pointer to PKIX_Error) that is expected to return |
| * NULL (i.e. to succeed). If "pkixTestErrorResult" is not NULL, |
| * "goto cleanup" is executed, where a testError call is made if there were |
| * unexpected results. This macro MUST NOT be called after the "cleanup" label. |
| * |
| * Example Usage: PKIX_TEST_EXPECT_NO_ERROR(pkixFunc_expected_to_succeed(...)); |
| */ |
| |
| #define PKIX_TEST_EXPECT_NO_ERROR(func) \ |
| do { \ |
| pkixTestErrorResult = (func); \ |
| if (pkixTestErrorResult) { \ |
| goto cleanup; \ |
| } \ |
| } while (0) |
| |
| /* |
| * PKIX_TEST_EXPECT_ERROR should be used to wrap a standard PKIX function call |
| * (one which returns a pointer to PKIX_Error) that is expected to return |
| * a non-NULL value (i.e. to fail). If "pkixTestErrorResult" is NULL, |
| * "pkixTestErrorMsg" is set to a standard string and "goto cleanup" |
| * is executed, where a testError call is made if there were unexpected |
| * results. This macro MUST NOT be called after the "cleanup" label. |
| * |
| * Example Usage: PKIX_TEST_EXPECT_ERROR(pkixFunc_expected_to_fail(...)); |
| */ |
| |
| #define PKIX_TEST_EXPECT_ERROR(func) \ |
| do { \ |
| pkixTestErrorResult = (func); \ |
| if (!pkixTestErrorResult) { \ |
| pkixTestErrorMsg = \ |
| "Should have thrown an error here."; \ |
| goto cleanup; \ |
| } \ |
| PKIX_TEST_DECREF_BC(pkixTestErrorResult); \ |
| } while (0) |
| |
| /* |
| * PKIX_TEST_DECREF_BC is a convenience macro which should only be called |
| * BEFORE the "cleanup" label ("BC"). If the input parameter is non-NULL, it |
| * DecRefs the input parameter and wraps the function with |
| * PKIX_TEST_EXPECT_NO_ERROR, which executes "goto cleanup" upon error. |
| * This macro MUST NOT be called after the "cleanup" label. |
| */ |
| |
| #define PKIX_TEST_DECREF_BC(obj) \ |
| do { \ |
| if (obj) { \ |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_DecRef((PKIX_PL_Object *)(obj), plContext)); \ |
| obj = NULL; \ |
| } \ |
| } while (0) |
| |
| /* |
| * PKIX_TEST_DECREF_AC is a convenience macro which should only be called |
| * AFTER the "cleanup" label ("AC"). If the input parameter is non-NULL, it |
| * DecRefs the input parameter. A pkixTestTempResult variable is used to prevent |
| * incorrectly overwriting pkixTestErrorResult with NULL. |
| * In the case DecRef succeeds, pkixTestTempResult will be NULL, and we won't |
| * overwrite a previously set pkixTestErrorResult (if any). If DecRef fails, |
| * then we do want to overwrite a previously set pkixTestErrorResult since a |
| * DecRef failure is fatal and may be indicative of memory corruption. |
| */ |
| |
| #define PKIX_TEST_DECREF_AC(obj) \ |
| do { \ |
| if (obj) { \ |
| PKIX_Error *pkixTestTempResult = NULL; \ |
| pkixTestTempResult = \ |
| PKIX_PL_Object_DecRef((PKIX_PL_Object *)(obj), plContext); \ |
| if (pkixTestTempResult) \ |
| pkixTestErrorResult = pkixTestTempResult; \ |
| obj = NULL; \ |
| } \ |
| } while (0) |
| |
| /* |
| * PKIX_TEST_RETURN must always be AFTER the "cleanup" label. It does nothing |
| * if everything went as expected. However, if there were unexpected results, |
| * PKIX_TEST_RETURN calls testError, which displays a standard failure message |
| * and increments the number of subtests that have failed. In the case |
| * of an unexpected error, testError is called using the error's description |
| * as an input and the error is DecRef'd. In the case of unexpected success |
| * testError is called with a standard string. |
| */ |
| #define PKIX_TEST_RETURN() \ |
| { \ |
| if (pkixTestErrorMsg) { \ |
| testError(pkixTestErrorMsg); \ |
| } else if (pkixTestErrorResult) { \ |
| pkixTestErrorMsg = \ |
| PKIX_Error2ASCII(pkixTestErrorResult, plContext); \ |
| if (pkixTestErrorMsg) { \ |
| testError(pkixTestErrorMsg); \ |
| PKIX_PL_Free((PKIX_PL_Object *)pkixTestErrorMsg, \ |
| plContext); \ |
| } else { \ |
| testError("PKIX_Error2ASCII Failed"); \ |
| } \ |
| if (pkixTestErrorResult != PKIX_ALLOC_ERROR()) { \ |
| PKIX_PL_Object_DecRef((PKIX_PL_Object *)pkixTestErrorResult, \ |
| plContext); \ |
| pkixTestErrorResult = NULL; \ |
| } \ |
| } \ |
| } |
| |
| /* |
| * PKIX_TEST_EQ_HASH_TOSTR_DUP is a convenience macro which executes the |
| * standard set of operations that test the Equals, Hashcode, ToString, and |
| * Duplicate functions of an object type. The goodObj, equalObj, and diffObj |
| * are as the names suggest. The expAscii parameter is the expected result of |
| * calling ToString on the goodObj. If expAscii is NULL, then ToString will |
| * not be called on the goodObj. The checkDuplicate parameter is treated as |
| * a Boolean to indicate whether the Duplicate function should be tested. If |
| * checkDuplicate is NULL, then Duplicate will not be called on the goodObj. |
| * The type is the name of the function's family. For example, if the type is |
| * Cert, this macro will call PKIX_PL_Cert_Equals, PKIX_PL_Cert_Hashcode, and |
| * PKIX_PL_Cert_ToString. |
| * |
| * Note: If goodObj uses the default Equals and Hashcode functions, then |
| * for goodObj and equalObj to be equal, they must have the same pointer value. |
| */ |
| #define PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObj, equalObj, diffObj, \ |
| expAscii, type, checkDuplicate) \ |
| do { \ |
| subTest("PKIX_PL_" #type "_Equals <match>"); \ |
| testEqualsHelper((PKIX_PL_Object *)(goodObj), \ |
| (PKIX_PL_Object *)(equalObj), \ |
| PKIX_TRUE, \ |
| plContext); \ |
| subTest("PKIX_PL_" #type "_Hashcode <match>"); \ |
| testHashcodeHelper((PKIX_PL_Object *)(goodObj), \ |
| (PKIX_PL_Object *)(equalObj), \ |
| PKIX_TRUE, \ |
| plContext); \ |
| subTest("PKIX_PL_" #type "_Equals <non-match>"); \ |
| testEqualsHelper((PKIX_PL_Object *)(goodObj), \ |
| (PKIX_PL_Object *)(diffObj), \ |
| PKIX_FALSE, \ |
| plContext); \ |
| subTest("PKIX_PL_" #type "_Hashcode <non-match>"); \ |
| testHashcodeHelper((PKIX_PL_Object *)(goodObj), \ |
| (PKIX_PL_Object *)(diffObj), \ |
| PKIX_FALSE, \ |
| plContext); \ |
| if (expAscii) { \ |
| subTest("PKIX_PL_" #type "_ToString"); \ |
| testToStringHelper((PKIX_PL_Object *)(goodObj), \ |
| (expAscii), \ |
| plContext); \ |
| } \ |
| if (checkDuplicate) { \ |
| subTest("PKIX_PL_" #type "_Duplicate"); \ |
| testDuplicateHelper((PKIX_PL_Object *)goodObj, plContext); \ |
| } \ |
| } while (0) |
| |
| /* |
| * PKIX_TEST_DECREF_BC is a convenience macro which should only be called |
| * BEFORE the "cleanup" label ("BC"). If the input parameter is non-NULL, it |
| * DecRefs the input parameter and wraps the function with |
| * PKIX_TEST_EXPECT_NO_ERROR, which executes "goto cleanup" upon error. |
| * This macro MUST NOT be called after the "cleanup" label. |
| */ |
| |
| #define PKIX_TEST_ABORT_ON_NULL(obj) \ |
| do { \ |
| if (!obj) { \ |
| goto cleanup; \ |
| } \ |
| } while (0) |
| |
| #define PKIX_TEST_ARENAS_ARG(arena) \ |
| (arena ? (PORT_Strcmp(arena, "arenas") ? PKIX_FALSE : (j++, PKIX_TRUE)) : PKIX_FALSE) |
| |
| #define PKIX_TEST_ERROR_RECEIVED (pkixTestErrorMsg || pkixTestErrorResult) |
| |
| /* see source file for function documentation */ |
| |
| void startTests(char *testName); |
| |
| void endTests(char *testName); |
| |
| void subTest(char *subTestName); |
| |
| void testError(char *msg); |
| |
| extern PKIX_Error * |
| _ErrorCheck(PKIX_Error *errorResult); |
| |
| extern PKIX_Error * |
| _OutputError(PKIX_Error *errorResult); |
| |
| char *PKIX_String2ASCII(PKIX_PL_String *string, void *plContext); |
| |
| char *PKIX_Error2ASCII(PKIX_Error *error, void *plContext); |
| |
| char *PKIX_Object2ASCII(PKIX_PL_Object *object); |
| |
| char *PKIX_Cert2ASCII(PKIX_PL_Cert *cert); |
| |
| void |
| testHashcodeHelper( |
| PKIX_PL_Object *goodObject, |
| PKIX_PL_Object *otherObject, |
| PKIX_Boolean match, |
| void *plContext); |
| |
| void |
| testToStringHelper( |
| PKIX_PL_Object *goodObject, |
| char *expected, |
| void *plContext); |
| |
| void |
| testEqualsHelper( |
| PKIX_PL_Object *goodObject, |
| PKIX_PL_Object *otherObject, |
| PKIX_Boolean match, |
| void *plContext); |
| |
| void |
| testDuplicateHelper( |
| PKIX_PL_Object *object, |
| void *plContext); |
| void |
| testErrorUndo(char *msg); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* TESTUTIL_H */ |