/*
* 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*/