| /* 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/. */ |
| /* |
| * test_hashtable.c |
| * |
| * Tests Hashtables |
| * |
| */ |
| |
| #include "testutil.h" |
| #include "testutil_nss.h" |
| |
| static void *plContext = NULL; |
| |
| static void |
| createHashTables( |
| PKIX_PL_HashTable **ht, |
| PKIX_PL_HashTable **ht2, |
| PKIX_PL_HashTable **ht3, |
| PKIX_PL_HashTable **ht4) |
| { |
| PKIX_TEST_STD_VARS(); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(1, 0, ht, plContext)); |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(5, 0, ht2, plContext)); |
| |
| /* at most two entries per bucket */ |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(1, 2, ht4, plContext)); |
| |
| *ht3 = *ht; |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)*ht3, plContext)); |
| |
| cleanup: |
| PKIX_TEST_RETURN(); |
| } |
| |
| static void |
| testAdd( |
| PKIX_PL_HashTable *ht, |
| PKIX_PL_HashTable *ht2, |
| PKIX_PL_String **testString, |
| PKIX_PL_String **testString2, |
| PKIX_PL_String **testString3, |
| PKIX_PL_OID **testOID) |
| { |
| char *dummyString = "test string 1"; |
| char *dummyString2 = "test string 2"; |
| char *dummyString3 = "test string 3"; |
| char *dummyOID = "2.11.22222.33333"; |
| |
| PKIX_TEST_STD_VARS(); |
| |
| /* Make some dummy objects */ |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create( |
| PKIX_ESCASCII, |
| dummyString, |
| PL_strlen(dummyString), |
| testString, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create( |
| PKIX_ESCASCII, |
| dummyString2, |
| PL_strlen(dummyString2), |
| testString2, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create( |
| PKIX_ESCASCII, |
| dummyString3, |
| PL_strlen(dummyString3), |
| testString3, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(dummyOID, testOID, plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht, |
| (PKIX_PL_Object *)*testString, |
| (PKIX_PL_Object *)*testString2, |
| plContext)); |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht2, |
| (PKIX_PL_Object *)*testString, |
| (PKIX_PL_Object *)*testString2, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht, |
| (PKIX_PL_Object *)*testString2, |
| (PKIX_PL_Object *)*testString, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht2, |
| (PKIX_PL_Object *)*testString2, |
| (PKIX_PL_Object *)*testString, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht, |
| (PKIX_PL_Object *)*testOID, |
| (PKIX_PL_Object *)*testOID, |
| plContext)); |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht2, |
| (PKIX_PL_Object *)*testOID, |
| (PKIX_PL_Object *)*testOID, |
| plContext)); |
| |
| cleanup: |
| PKIX_TEST_RETURN(); |
| } |
| |
| static void |
| testAddFIFO( |
| PKIX_PL_HashTable *ht, |
| PKIX_PL_String **testString, |
| PKIX_PL_String **testString2, |
| PKIX_PL_String **testString3) |
| { |
| PKIX_PL_String *targetString = NULL; |
| PKIX_Boolean cmpResult; |
| |
| PKIX_TEST_STD_VARS(); |
| |
| /* |
| * ht is created as one bucket, two entries per bucket. Since we add |
| * three items to the ht, we expect the first one to be deleted. |
| */ |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht, |
| (PKIX_PL_Object *)*testString, |
| (PKIX_PL_Object *)*testString, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht, |
| (PKIX_PL_Object *)*testString2, |
| (PKIX_PL_Object *)*testString2, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht, |
| (PKIX_PL_Object *)*testString3, |
| (PKIX_PL_Object *)*testString3, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht, |
| (PKIX_PL_Object *)*testString, |
| (PKIX_PL_Object **)&targetString, |
| plContext)); |
| if (targetString != NULL) { |
| testError("HashTable_Lookup retrieved a supposed deleted item"); |
| PKIX_TEST_DECREF_BC(targetString); |
| } |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht, |
| (PKIX_PL_Object *)*testString3, |
| (PKIX_PL_Object **)&targetString, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals( |
| (PKIX_PL_Object *)targetString, |
| (PKIX_PL_Object *)*testString3, |
| &cmpResult, |
| plContext)); |
| if (cmpResult != PKIX_TRUE) { |
| testError("HashTable_Lookup failed"); |
| } |
| PKIX_TEST_DECREF_BC(targetString); |
| |
| cleanup: |
| PKIX_TEST_RETURN(); |
| } |
| |
| static void |
| testLookup( |
| PKIX_PL_HashTable *ht, |
| PKIX_PL_HashTable *ht2, |
| PKIX_PL_String *testString, |
| PKIX_PL_String *testString2, |
| PKIX_PL_String *testString3, |
| PKIX_PL_OID *testOID) |
| { |
| PKIX_PL_String *targetString = NULL; |
| PKIX_PL_String *targetOID = NULL; |
| PKIX_Boolean cmpResult; |
| |
| PKIX_TEST_STD_VARS(); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht, |
| (PKIX_PL_Object *)testString, |
| (PKIX_PL_Object **)&targetString, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals( |
| (PKIX_PL_Object *)targetString, |
| (PKIX_PL_Object *)testString2, |
| &cmpResult, |
| plContext)); |
| if (cmpResult != PKIX_TRUE) { |
| testError("HashTable_Lookup failed"); |
| } |
| PKIX_TEST_DECREF_BC(targetString); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht2, |
| (PKIX_PL_Object *)testString, |
| (PKIX_PL_Object **)&targetString, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals( |
| (PKIX_PL_Object *)targetString, |
| (PKIX_PL_Object *)testString2, |
| &cmpResult, |
| plContext)); |
| if (cmpResult != PKIX_TRUE) { |
| testError("HashTable_Lookup failed"); |
| } |
| PKIX_TEST_DECREF_BC(targetString); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht2, |
| (PKIX_PL_Object *)testString2, |
| (PKIX_PL_Object **)&targetString, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals( |
| (PKIX_PL_Object *)targetString, |
| (PKIX_PL_Object *)testString, |
| &cmpResult, |
| plContext)); |
| if (cmpResult != PKIX_TRUE) { |
| testError("HashTable_Lookup failed"); |
| } |
| PKIX_TEST_DECREF_BC(targetString); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht, |
| (PKIX_PL_Object *)testOID, |
| (PKIX_PL_Object **)&targetOID, |
| plContext)); |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)targetOID, &targetString, plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals( |
| (PKIX_PL_Object *)targetOID, |
| (PKIX_PL_Object *)testOID, |
| &cmpResult, |
| plContext)); |
| if (cmpResult != PKIX_TRUE) { |
| testError("HashTable_Lookup failed"); |
| } |
| PKIX_TEST_DECREF_BC(targetString); |
| PKIX_TEST_DECREF_BC(targetOID); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht2, |
| (PKIX_PL_Object *)testOID, |
| (PKIX_PL_Object **)&targetOID, |
| plContext)); |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)targetOID, &targetString, plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals( |
| (PKIX_PL_Object *)targetOID, |
| (PKIX_PL_Object *)testOID, |
| &cmpResult, |
| plContext)); |
| if (cmpResult != PKIX_TRUE) { |
| testError("HashTable_Lookup failed"); |
| } |
| PKIX_TEST_DECREF_BC(targetString); |
| PKIX_TEST_DECREF_BC(targetOID); |
| |
| (void)printf("Looking up item not in HashTable.\n"); |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht, |
| (PKIX_PL_Object *)testString3, |
| (PKIX_PL_Object **)&targetString, |
| plContext)); |
| if (targetString == NULL) |
| (void)printf("\tCorrectly returned NULL.\n"); |
| else |
| testError("Hashtable did not return NULL value as expected"); |
| |
| cleanup: |
| PKIX_TEST_RETURN(); |
| } |
| |
| static void |
| testRemove( |
| PKIX_PL_HashTable *ht, |
| PKIX_PL_HashTable *ht2, |
| PKIX_PL_String *testString, |
| PKIX_PL_String *testString2, |
| PKIX_PL_OID *testOID) |
| { |
| |
| PKIX_TEST_STD_VARS(); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Remove(ht, |
| (PKIX_PL_Object *)testString, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Remove(ht, |
| (PKIX_PL_Object *)testOID, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Remove(ht2, |
| (PKIX_PL_Object *)testString2, |
| plContext)); |
| |
| PKIX_TEST_EXPECT_ERROR(PKIX_PL_HashTable_Remove(ht, |
| (PKIX_PL_Object *)testString, |
| plContext)); |
| |
| cleanup: |
| PKIX_TEST_RETURN(); |
| } |
| |
| static void |
| testDestroy( |
| PKIX_PL_HashTable *ht, |
| PKIX_PL_HashTable *ht2, |
| PKIX_PL_HashTable *ht3, |
| PKIX_PL_HashTable *ht4) |
| { |
| PKIX_TEST_STD_VARS(); |
| |
| PKIX_TEST_DECREF_BC(ht); |
| PKIX_TEST_DECREF_BC(ht2); |
| PKIX_TEST_DECREF_BC(ht3); |
| PKIX_TEST_DECREF_BC(ht4); |
| |
| cleanup: |
| PKIX_TEST_RETURN(); |
| } |
| |
| int |
| test_hashtable(int argc, char *argv[]) |
| { |
| |
| PKIX_PL_HashTable *ht, *ht2, *ht3, *ht4; |
| PKIX_PL_String *testString, *testString2, *testString3; |
| PKIX_PL_OID *testOID; |
| PKIX_UInt32 actualMinorVersion; |
| PKIX_UInt32 j = 0; |
| |
| PKIX_TEST_STD_VARS(); |
| |
| startTests("HashTables"); |
| |
| PKIX_TEST_EXPECT_NO_ERROR( |
| PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext)); |
| |
| subTest("PKIX_PL_HashTable_Create"); |
| createHashTables(&ht, &ht2, &ht3, &ht4); |
| |
| PKIX_TEST_EQ_HASH_TOSTR_DUP(ht, |
| ht3, |
| ht2, |
| NULL, |
| HashTable, |
| PKIX_FALSE); |
| |
| subTest("PKIX_PL_HashTable_Add"); |
| testAdd(ht, ht2, &testString, &testString2, &testString3, &testOID); |
| |
| subTest("PKIX_PL_HashTable_ADD - with Bucket Size limit"); |
| testAddFIFO(ht4, &testString, &testString2, &testString3); |
| |
| subTest("PKIX_PL_HashTable_Lookup"); |
| testLookup(ht, ht2, testString, testString2, testString3, testOID); |
| |
| subTest("PKIX_PL_HashTable_Remove"); |
| testRemove(ht, ht2, testString, testString2, testOID); |
| |
| PKIX_TEST_DECREF_BC(testString); |
| PKIX_TEST_DECREF_BC(testString2); |
| PKIX_TEST_DECREF_BC(testString3); |
| PKIX_TEST_DECREF_BC(testOID); |
| |
| subTest("PKIX_PL_HashTable_Destroy"); |
| testDestroy(ht, ht2, ht3, ht4); |
| |
| cleanup: |
| |
| PKIX_Shutdown(plContext); |
| |
| endTests("BigInt"); |
| |
| return (0); |
| } |