michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: /* michael@0: * testutil.c michael@0: * michael@0: * Utility error handling functions michael@0: * michael@0: */ michael@0: michael@0: #include "testutil.h" michael@0: michael@0: /* michael@0: * static global variable to keep track of total number of errors for michael@0: * a particular test suite (eg. all the OID tests) michael@0: */ michael@0: static int errCount = 0; michael@0: michael@0: /* michael@0: * FUNCTION: startTests michael@0: * DESCRIPTION: michael@0: * michael@0: * Prints standard message for starting the test suite with the name pointed michael@0: * to by "testName". This function should be called in the beginning of every michael@0: * test suite. michael@0: * michael@0: * PARAMETERS: michael@0: * "testName" michael@0: * Address of string representing name of test suite. michael@0: * THREAD SAFETY: michael@0: * Not Thread Safe - assumes exclusive access to "errCount" michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns nothing. michael@0: */ michael@0: void michael@0: startTests(char *testName) michael@0: { michael@0: (void) printf("*START OF TESTS FOR %s:\n", testName); michael@0: errCount = 0; michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: endTests michael@0: * DESCRIPTION: michael@0: * michael@0: * Prints standard message for ending the test suite with the name pointed michael@0: * to by "testName", followed by a success/failure message. This function michael@0: * should be called at the end of every test suite. michael@0: * michael@0: * PARAMETERS: michael@0: * "testName" michael@0: * Address of string representing name of test suite. michael@0: * THREAD SAFETY: michael@0: * Not Thread Safe - assumes exclusive access to "errCount" michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns nothing. michael@0: */ michael@0: void michael@0: endTests(char *testName) michael@0: { michael@0: char plural = ' '; michael@0: michael@0: (void) printf("*END OF TESTS FOR %s: ", testName); michael@0: if (errCount > 0) { michael@0: if (errCount > 1) plural = 's'; michael@0: (void) printf("%d SUBTEST%c FAILED.\n\n", errCount, plural); michael@0: } else { michael@0: (void) printf("ALL TESTS COMPLETED SUCCESSFULLY.\n\n"); michael@0: } michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: subTest michael@0: * DESCRIPTION: michael@0: * michael@0: * Prints standard message for starting the subtest with the name pointed to michael@0: * by "subTestName". This function should be called at the beginning of each michael@0: * subtest. michael@0: * michael@0: * PARAMETERS: michael@0: * "subTestName" michael@0: * Address of string representing name of subTest. michael@0: * THREAD SAFETY: michael@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns nothing. michael@0: */ michael@0: void michael@0: subTest(char *subTestName) michael@0: { michael@0: (void) printf("TESTING: %s ...\n", subTestName); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: testErrorUndo michael@0: * DESCRIPTION: michael@0: * michael@0: * Decrements the global variable "errCount" and prints a test failure michael@0: * expected message followed by the string pointed to by "msg". This function michael@0: * should be called when an expected error condition is encountered in the michael@0: * tests. Calling this function *correct* the previous errCount increment. michael@0: * It should only be called ONCE per subtest. michael@0: * michael@0: * PARAMETERS: michael@0: * "msg" michael@0: * Address of text of error message. michael@0: * THREAD SAFETY: michael@0: * Not Thread Safe - assumes exclusive access to "errCount" michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns nothing. michael@0: */ michael@0: void michael@0: testErrorUndo(char *msg) michael@0: { michael@0: --errCount; michael@0: (void) printf("TEST FAILURE *** EXPECTED *** :%s\n", msg); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: testError michael@0: * DESCRIPTION: michael@0: * michael@0: * Increments the global variable "errCount" and prints a standard test michael@0: * failure message followed by the string pointed to by "msg". This function michael@0: * should be called when an unexpected error condition is encountered in the michael@0: * tests. It should only be called ONCE per subtest. michael@0: * michael@0: * PARAMETERS: michael@0: * "msg" michael@0: * Address of text of error message. michael@0: * THREAD SAFETY: michael@0: * Not Thread Safe - assumes exclusive access to "errCount" michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns nothing. michael@0: */ michael@0: void michael@0: testError(char *msg) michael@0: { michael@0: ++errCount; michael@0: (void) printf("TEST FAILURE: %s\n", msg); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: PKIX_String2ASCII michael@0: * DESCRIPTION: michael@0: * michael@0: * Converts String object pointed to by "string" to its ASCII representation michael@0: * and returns the converted value. Returns NULL upon failure. michael@0: * michael@0: * XXX Might want to use ESCASCII_DEBUG to show control characters, etc. michael@0: * michael@0: * PARAMETERS: michael@0: * "string" michael@0: * Address of String to be converted to ASCII. Must be non-NULL. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns the ASCII representation of "string" upon success; michael@0: * NULL upon failure. michael@0: */ michael@0: char * michael@0: PKIX_String2ASCII(PKIX_PL_String *string, void *plContext) michael@0: { michael@0: PKIX_UInt32 length; michael@0: char *asciiString = NULL; michael@0: PKIX_Error *errorResult; michael@0: michael@0: errorResult = PKIX_PL_String_GetEncoded michael@0: (string, michael@0: PKIX_ESCASCII, michael@0: (void **)&asciiString, michael@0: &length, michael@0: plContext); michael@0: michael@0: if (errorResult) goto cleanup; michael@0: michael@0: cleanup: michael@0: michael@0: if (errorResult){ michael@0: return (NULL); michael@0: } michael@0: michael@0: return (asciiString); michael@0: michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: PKIX_Error2ASCII michael@0: * DESCRIPTION: michael@0: * michael@0: * Converts Error pointed to by "error" to its ASCII representation and michael@0: * returns the converted value. Returns NULL upon failure. michael@0: * michael@0: * PARAMETERS: michael@0: * "error" michael@0: * Address of Error to be converted to ASCII. Must be non-NULL. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns the ASCII representation of "error" upon success; michael@0: * NULL upon failure. michael@0: */ michael@0: char * michael@0: PKIX_Error2ASCII(PKIX_Error *error, void *plContext) michael@0: { michael@0: PKIX_UInt32 length; michael@0: char *asciiString = NULL; michael@0: PKIX_PL_String *pkixString = NULL; michael@0: PKIX_Error *errorResult = NULL; michael@0: michael@0: errorResult = PKIX_PL_Object_ToString michael@0: ((PKIX_PL_Object*)error, &pkixString, plContext); michael@0: if (errorResult) goto cleanup; michael@0: michael@0: errorResult = PKIX_PL_String_GetEncoded michael@0: (pkixString, michael@0: PKIX_ESCASCII, michael@0: (void **)&asciiString, michael@0: &length, michael@0: plContext); michael@0: michael@0: cleanup: michael@0: michael@0: if (pkixString){ michael@0: if (PKIX_PL_Object_DecRef michael@0: ((PKIX_PL_Object*)pkixString, plContext)){ michael@0: return (NULL); michael@0: } michael@0: } michael@0: michael@0: if (errorResult){ michael@0: return (NULL); michael@0: } michael@0: michael@0: return (asciiString); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: PKIX_Object2ASCII michael@0: * DESCRIPTION: michael@0: * michael@0: * Converts Object pointed to by "object" to its ASCII representation and michael@0: * returns the converted value. Returns NULL upon failure. michael@0: * michael@0: * PARAMETERS: michael@0: * "object" michael@0: * Address of Object to be converted to ASCII. Must be non-NULL. michael@0: * THREAD SAFETY: michael@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns the ASCII representation of "object" upon success; michael@0: * NULL upon failure. michael@0: */ michael@0: char * michael@0: PKIX_Object2ASCII(PKIX_PL_Object *object) michael@0: { michael@0: PKIX_UInt32 length; michael@0: char *asciiString = NULL; michael@0: PKIX_PL_String *pkixString = NULL; michael@0: PKIX_Error *errorResult = NULL; michael@0: michael@0: errorResult = PKIX_PL_Object_ToString michael@0: (object, &pkixString, NULL); michael@0: if (errorResult) goto cleanup; michael@0: michael@0: errorResult = PKIX_PL_String_GetEncoded michael@0: (pkixString, PKIX_ESCASCII, (void **)&asciiString, &length, NULL); michael@0: michael@0: cleanup: michael@0: michael@0: if (pkixString){ michael@0: if (PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixString, NULL)){ michael@0: return (NULL); michael@0: } michael@0: } michael@0: michael@0: if (errorResult){ michael@0: return (NULL); michael@0: } michael@0: michael@0: return (asciiString); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: PKIX_Cert2ASCII michael@0: * DESCRIPTION: michael@0: * michael@0: * Converts Cert pointed to by "cert" to its partial ASCII representation and michael@0: * returns the converted value. Returns NULL upon failure. michael@0: * michael@0: * PARAMETERS: michael@0: * "cert" michael@0: * Address of Cert to be converted to ASCII. Must be non-NULL. michael@0: * THREAD SAFETY: michael@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns the partial ASCII representation of "cert" upon success; michael@0: * NULL upon failure. michael@0: */ michael@0: char * michael@0: PKIX_Cert2ASCII(PKIX_PL_Cert *cert) michael@0: { michael@0: PKIX_PL_X500Name *issuer = NULL; michael@0: void *issuerAscii = NULL; michael@0: PKIX_PL_X500Name *subject = NULL; michael@0: void *subjectAscii = NULL; michael@0: void *asciiString = NULL; michael@0: PKIX_Error *errorResult = NULL; michael@0: PKIX_UInt32 numChars; michael@0: michael@0: /* Issuer */ michael@0: errorResult = PKIX_PL_Cert_GetIssuer(cert, &issuer, NULL); michael@0: if (errorResult) goto cleanup; michael@0: michael@0: issuerAscii = PKIX_Object2ASCII((PKIX_PL_Object*)issuer); michael@0: michael@0: /* Subject */ michael@0: errorResult = PKIX_PL_Cert_GetSubject(cert, &subject, NULL); michael@0: if (errorResult) goto cleanup; michael@0: michael@0: if (subject){ michael@0: subjectAscii = PKIX_Object2ASCII((PKIX_PL_Object*)subject); michael@0: } michael@0: michael@0: errorResult = PKIX_PL_Malloc(200, &asciiString, NULL); michael@0: if (errorResult) goto cleanup; michael@0: michael@0: numChars = michael@0: PR_snprintf michael@0: (asciiString, michael@0: 200, michael@0: "Issuer=%s\nSubject=%s\n", michael@0: issuerAscii, michael@0: subjectAscii); michael@0: michael@0: if (!numChars) goto cleanup; michael@0: michael@0: cleanup: michael@0: michael@0: if (issuer){ michael@0: if (PKIX_PL_Object_DecRef((PKIX_PL_Object*)issuer, NULL)){ michael@0: return (NULL); michael@0: } michael@0: } michael@0: michael@0: if (subject){ michael@0: if (PKIX_PL_Object_DecRef((PKIX_PL_Object*)subject, NULL)){ michael@0: return (NULL); michael@0: } michael@0: } michael@0: michael@0: if (PKIX_PL_Free((PKIX_PL_Object*)issuerAscii, NULL)){ michael@0: return (NULL); michael@0: } michael@0: michael@0: if (PKIX_PL_Free((PKIX_PL_Object*)subjectAscii, NULL)){ michael@0: return (NULL); michael@0: } michael@0: michael@0: if (errorResult){ michael@0: return (NULL); michael@0: } michael@0: michael@0: return (asciiString); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: testHashcodeHelper michael@0: * DESCRIPTION: michael@0: * michael@0: * Computes the hashcode of the Object pointed to by "goodObject" and the michael@0: * Object pointed to by "otherObject" and compares them. If the result of the michael@0: * comparison is not the desired match as specified by "match", an error michael@0: * message is generated. michael@0: * michael@0: * PARAMETERS: michael@0: * "goodObject" michael@0: * Address of an object. Must be non-NULL. michael@0: * "otherObject" michael@0: * Address of another object. Must be non-NULL. michael@0: * "match" michael@0: * Boolean value representing the desired comparison result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns nothing. michael@0: */ michael@0: void michael@0: testHashcodeHelper( michael@0: PKIX_PL_Object *goodObject, michael@0: PKIX_PL_Object *otherObject, michael@0: PKIX_Boolean match, michael@0: void *plContext) michael@0: { michael@0: michael@0: PKIX_UInt32 goodHash; michael@0: PKIX_UInt32 otherHash; michael@0: PKIX_Boolean cmpResult; michael@0: PKIX_TEST_STD_VARS(); michael@0: michael@0: PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Hashcode michael@0: ((PKIX_PL_Object *)goodObject, &goodHash, plContext)); michael@0: michael@0: PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Hashcode michael@0: ((PKIX_PL_Object *)otherObject, &otherHash, plContext)); michael@0: michael@0: cmpResult = (goodHash == otherHash); michael@0: michael@0: if ((match && !cmpResult) || (!match && cmpResult)){ michael@0: testError("unexpected mismatch"); michael@0: (void) printf("Hash1:\t%d\n", goodHash); michael@0: (void) printf("Hash2:\t%d\n", otherHash); michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_TEST_RETURN(); michael@0: michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: testToStringHelper michael@0: * DESCRIPTION: michael@0: * michael@0: * Calls toString on the Object pointed to by "goodObject" and compares the michael@0: * result to the string pointed to by "expected". If the results are not michael@0: * equal, an error message is generated. michael@0: * michael@0: * PARAMETERS: michael@0: * "goodObject" michael@0: * Address of Object. Must be non-NULL. michael@0: * "expected" michael@0: * Address of the desired string. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns nothing. michael@0: */ michael@0: void michael@0: testToStringHelper( michael@0: PKIX_PL_Object *goodObject, michael@0: char *expected, michael@0: void *plContext) michael@0: { michael@0: PKIX_PL_String *stringRep = NULL; michael@0: char *actual = NULL; michael@0: PKIX_TEST_STD_VARS(); michael@0: michael@0: PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString michael@0: (goodObject, &stringRep, plContext)); michael@0: michael@0: actual = PKIX_String2ASCII(stringRep, plContext); michael@0: if (actual == NULL){ michael@0: pkixTestErrorMsg = "PKIX_String2ASCII Failed"; michael@0: goto cleanup; michael@0: } michael@0: michael@0: /* michael@0: * If you are having trouble matching the string, uncomment the michael@0: * PL_strstr function to figure out what's going on. michael@0: */ michael@0: michael@0: /* michael@0: if (PL_strstr(actual, expected) == NULL){ michael@0: testError("PL_strstr failed"); michael@0: } michael@0: */ michael@0: michael@0: michael@0: if (PL_strcmp(actual, expected) != 0){ michael@0: testError("unexpected mismatch"); michael@0: (void) printf("Actual value:\t%s\n", actual); michael@0: (void) printf("Expected value:\t%s\n", expected); michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_PL_Free(actual, plContext); michael@0: michael@0: PKIX_TEST_DECREF_AC(stringRep); michael@0: michael@0: PKIX_TEST_RETURN(); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: testEqualsHelper michael@0: * DESCRIPTION: michael@0: * michael@0: * Checks if the Object pointed to by "goodObject" is Equal to the Object michael@0: * pointed to by "otherObject". If the result of the check is not the desired michael@0: * match as specified by "match", an error message is generated. michael@0: * michael@0: * PARAMETERS: michael@0: * "goodObject" michael@0: * Address of an Object. Must be non-NULL. michael@0: * "otherObject" michael@0: * Address of another Object. Must be non-NULL. michael@0: * "match" michael@0: * Boolean value representing the desired comparison result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns nothing. michael@0: */ michael@0: void michael@0: testEqualsHelper( michael@0: PKIX_PL_Object *goodObject, michael@0: PKIX_PL_Object *otherObject, michael@0: PKIX_Boolean match, michael@0: void *plContext) michael@0: { michael@0: michael@0: PKIX_Boolean cmpResult; michael@0: PKIX_TEST_STD_VARS(); michael@0: michael@0: PKIX_TEST_EXPECT_NO_ERROR michael@0: (PKIX_PL_Object_Equals michael@0: (goodObject, otherObject, &cmpResult, plContext)); michael@0: michael@0: if ((match && !cmpResult) || (!match && cmpResult)){ michael@0: testError("unexpected mismatch"); michael@0: (void) printf("Actual value:\t%d\n", cmpResult); michael@0: (void) printf("Expected value:\t%d\n", match); michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_TEST_RETURN(); michael@0: } michael@0: michael@0: michael@0: /* michael@0: * FUNCTION: testDuplicateHelper michael@0: * DESCRIPTION: michael@0: * Checks if the Object pointed to by "object" is equal to its duplicate. michael@0: * If the result of the check is not equality, an error message is generated. michael@0: * PARAMETERS: michael@0: * "object" michael@0: * Address of Object. Must be non-NULL. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns nothing. michael@0: */ michael@0: void michael@0: testDuplicateHelper(PKIX_PL_Object *object, void *plContext) michael@0: { michael@0: PKIX_PL_Object *newObject = NULL; michael@0: PKIX_Boolean cmpResult; michael@0: michael@0: PKIX_TEST_STD_VARS(); michael@0: michael@0: PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate michael@0: (object, &newObject, plContext)); michael@0: michael@0: PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals michael@0: (object, newObject, &cmpResult, plContext)); michael@0: michael@0: if (!cmpResult){ michael@0: testError("unexpected mismatch"); michael@0: (void) printf("Actual value:\t%d\n", cmpResult); michael@0: (void) printf("Expected value:\t%d\n", PKIX_TRUE); michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_TEST_DECREF_AC(newObject); michael@0: michael@0: PKIX_TEST_RETURN(); michael@0: }