| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* |
| * Test the hash table functions. |
| */ |
| #include "Dalvik.h" |
| |
| #include <stdlib.h> |
| |
| #ifndef NDEBUG |
| |
| #define kNumTestEntries 14 |
| |
| /* |
| * Test foreach. |
| */ |
| static int printFunc(void* data, void* arg) |
| { |
| //printf(" '%s'\n", (const char*) data); |
| // (should verify strings) |
| |
| int* count = (int*) arg; |
| (*count)++; |
| return 0; |
| } |
| static void dumpForeach(HashTable* pTab) |
| { |
| int count = 0; |
| |
| //printf("Print from foreach:\n"); |
| dvmHashForeach(pTab, printFunc, &count); |
| if (count != kNumTestEntries) { |
| ALOGE("TestHash foreach test failed"); |
| assert(false); |
| } |
| } |
| |
| /* |
| * Test iterator. |
| */ |
| static void dumpIterator(HashTable* pTab) |
| { |
| int count = 0; |
| |
| //printf("Print from iterator:\n"); |
| HashIter iter; |
| for (dvmHashIterBegin(pTab, &iter); !dvmHashIterDone(&iter); |
| dvmHashIterNext(&iter)) |
| { |
| //const char* str = (const char*) dvmHashIterData(&iter); |
| //printf(" '%s'\n", str); |
| // (should verify strings) |
| count++; |
| } |
| if (count != kNumTestEntries) { |
| ALOGE("TestHash iterator test failed"); |
| assert(false); |
| } |
| } |
| |
| /* |
| * Some quick hash table tests. |
| */ |
| bool dvmTestHash() |
| { |
| HashTable* pTab; |
| char tmpStr[64]; |
| const char* str; |
| u4 hash; |
| int i; |
| |
| ALOGV("TestHash BEGIN"); |
| |
| pTab = dvmHashTableCreate(dvmHashSize(12), free); |
| if (pTab == NULL) |
| return false; |
| |
| dvmHashTableLock(pTab); |
| |
| /* add some entries */ |
| for (i = 0; i < kNumTestEntries; i++) { |
| sprintf(tmpStr, "entry %d", i); |
| hash = dvmComputeUtf8Hash(tmpStr); |
| dvmHashTableLookup(pTab, hash, strdup(tmpStr), |
| (HashCompareFunc) strcmp, true); |
| } |
| |
| dvmHashTableUnlock(pTab); |
| |
| /* make sure we can find all entries */ |
| for (i = 0; i < kNumTestEntries; i++) { |
| sprintf(tmpStr, "entry %d", i); |
| hash = dvmComputeUtf8Hash(tmpStr); |
| str = (const char*) dvmHashTableLookup(pTab, hash, tmpStr, |
| (HashCompareFunc) strcmp, false); |
| if (str == NULL) { |
| ALOGE("TestHash: failure: could not find '%s'", tmpStr); |
| /* return false */ |
| } |
| } |
| |
| /* make sure it behaves correctly when entry not found and !doAdd */ |
| sprintf(tmpStr, "entry %d", 17); |
| hash = dvmComputeUtf8Hash(tmpStr); |
| str = (const char*) dvmHashTableLookup(pTab, hash, tmpStr, |
| (HashCompareFunc) strcmp, false); |
| if (str == NULL) { |
| /* good */ |
| } else { |
| ALOGE("TestHash found nonexistent string (improper add?)"); |
| } |
| |
| dumpForeach(pTab); |
| dumpIterator(pTab); |
| |
| /* make sure they all get freed */ |
| dvmHashTableFree(pTab); |
| |
| |
| /* |
| * Round 2: verify probing & tombstones. |
| */ |
| pTab = dvmHashTableCreate(dvmHashSize(2), free); |
| if (pTab == NULL) |
| return false; |
| |
| hash = 0; |
| |
| /* two entries, same hash, different values */ |
| const char* str1; |
| str1 = (char*) dvmHashTableLookup(pTab, hash, strdup("one"), |
| (HashCompareFunc) strcmp, true); |
| assert(str1 != NULL); |
| str = (const char*) dvmHashTableLookup(pTab, hash, strdup("two"), |
| (HashCompareFunc) strcmp, true); |
| |
| /* remove the first one */ |
| if (!dvmHashTableRemove(pTab, hash, (void*)str1)) |
| ALOGE("TestHash failed to delete item"); |
| else |
| free((void*)str1); // "Remove" doesn't call the free func |
| |
| /* make sure iterator doesn't included deleted entries */ |
| int count = 0; |
| HashIter iter; |
| for (dvmHashIterBegin(pTab, &iter); !dvmHashIterDone(&iter); |
| dvmHashIterNext(&iter)) |
| { |
| count++; |
| } |
| if (count != 1) { |
| ALOGE("TestHash wrong number of entries (%d)", count); |
| } |
| |
| /* see if we can find them */ |
| str = (const char*) dvmHashTableLookup(pTab, hash, (void*)"one", |
| (HashCompareFunc) strcmp,false); |
| if (str != NULL) |
| ALOGE("TestHash deleted entry has returned!"); |
| str = (const char*) dvmHashTableLookup(pTab, hash, (void*)"two", |
| (HashCompareFunc) strcmp,false); |
| if (str == NULL) |
| ALOGE("TestHash entry vanished"); |
| |
| /* force a table realloc to exercise tombstone removal */ |
| for (i = 0; i < 20; i++) { |
| sprintf(tmpStr, "entry %d", i); |
| str = (const char*) dvmHashTableLookup(pTab, hash, strdup(tmpStr), |
| (HashCompareFunc) strcmp, true); |
| assert(str != NULL); |
| } |
| |
| dvmHashTableFree(pTab); |
| ALOGV("TestHash END"); |
| |
| return true; |
| } |
| |
| #endif /*NDEBUG*/ |