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