1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * Test the hash table functions.
19 */
20 #include "Dalvik.h"
21
22 #include <stdlib.h>
23
24 #ifndef NDEBUG
25
26 #define kNumTestEntries 14
27
28 /*
29 * Test foreach.
30 */
printFunc(void * data,void * arg)31 static int printFunc(void* data, void* arg)
32 {
33 //printf(" '%s'\n", (const char*) data);
34 // (should verify strings)
35
36 int* count = (int*) arg;
37 (*count)++;
38 return 0;
39 }
dumpForeach(HashTable * pTab)40 static void dumpForeach(HashTable* pTab)
41 {
42 int count = 0;
43
44 //printf("Print from foreach:\n");
45 dvmHashForeach(pTab, printFunc, &count);
46 if (count != kNumTestEntries) {
47 ALOGE("TestHash foreach test failed");
48 assert(false);
49 }
50 }
51
52 /*
53 * Test iterator.
54 */
dumpIterator(HashTable * pTab)55 static void dumpIterator(HashTable* pTab)
56 {
57 int count = 0;
58
59 //printf("Print from iterator:\n");
60 HashIter iter;
61 for (dvmHashIterBegin(pTab, &iter); !dvmHashIterDone(&iter);
62 dvmHashIterNext(&iter))
63 {
64 //const char* str = (const char*) dvmHashIterData(&iter);
65 //printf(" '%s'\n", str);
66 // (should verify strings)
67 count++;
68 }
69 if (count != kNumTestEntries) {
70 ALOGE("TestHash iterator test failed");
71 assert(false);
72 }
73 }
74
75 /*
76 * Some quick hash table tests.
77 */
dvmTestHash()78 bool dvmTestHash()
79 {
80 HashTable* pTab;
81 char tmpStr[64];
82 const char* str;
83 u4 hash;
84 int i;
85
86 ALOGV("TestHash BEGIN");
87
88 pTab = dvmHashTableCreate(dvmHashSize(12), free);
89 if (pTab == NULL)
90 return false;
91
92 dvmHashTableLock(pTab);
93
94 /* add some entries */
95 for (i = 0; i < kNumTestEntries; i++) {
96 sprintf(tmpStr, "entry %d", i);
97 hash = dvmComputeUtf8Hash(tmpStr);
98 dvmHashTableLookup(pTab, hash, strdup(tmpStr),
99 (HashCompareFunc) strcmp, true);
100 }
101
102 dvmHashTableUnlock(pTab);
103
104 /* make sure we can find all entries */
105 for (i = 0; i < kNumTestEntries; i++) {
106 sprintf(tmpStr, "entry %d", i);
107 hash = dvmComputeUtf8Hash(tmpStr);
108 str = (const char*) dvmHashTableLookup(pTab, hash, tmpStr,
109 (HashCompareFunc) strcmp, false);
110 if (str == NULL) {
111 ALOGE("TestHash: failure: could not find '%s'", tmpStr);
112 /* return false */
113 }
114 }
115
116 /* make sure it behaves correctly when entry not found and !doAdd */
117 sprintf(tmpStr, "entry %d", 17);
118 hash = dvmComputeUtf8Hash(tmpStr);
119 str = (const char*) dvmHashTableLookup(pTab, hash, tmpStr,
120 (HashCompareFunc) strcmp, false);
121 if (str == NULL) {
122 /* good */
123 } else {
124 ALOGE("TestHash found nonexistent string (improper add?)");
125 }
126
127 dumpForeach(pTab);
128 dumpIterator(pTab);
129
130 /* make sure they all get freed */
131 dvmHashTableFree(pTab);
132
133
134 /*
135 * Round 2: verify probing & tombstones.
136 */
137 pTab = dvmHashTableCreate(dvmHashSize(2), free);
138 if (pTab == NULL)
139 return false;
140
141 hash = 0;
142
143 /* two entries, same hash, different values */
144 const char* str1;
145 str1 = (char*) dvmHashTableLookup(pTab, hash, strdup("one"),
146 (HashCompareFunc) strcmp, true);
147 assert(str1 != NULL);
148 str = (const char*) dvmHashTableLookup(pTab, hash, strdup("two"),
149 (HashCompareFunc) strcmp, true);
150
151 /* remove the first one */
152 if (!dvmHashTableRemove(pTab, hash, (void*)str1))
153 ALOGE("TestHash failed to delete item");
154 else
155 free((void*)str1); // "Remove" doesn't call the free func
156
157 /* make sure iterator doesn't included deleted entries */
158 int count = 0;
159 HashIter iter;
160 for (dvmHashIterBegin(pTab, &iter); !dvmHashIterDone(&iter);
161 dvmHashIterNext(&iter))
162 {
163 count++;
164 }
165 if (count != 1) {
166 ALOGE("TestHash wrong number of entries (%d)", count);
167 }
168
169 /* see if we can find them */
170 str = (const char*) dvmHashTableLookup(pTab, hash, (void*)"one",
171 (HashCompareFunc) strcmp,false);
172 if (str != NULL)
173 ALOGE("TestHash deleted entry has returned!");
174 str = (const char*) dvmHashTableLookup(pTab, hash, (void*)"two",
175 (HashCompareFunc) strcmp,false);
176 if (str == NULL)
177 ALOGE("TestHash entry vanished");
178
179 /* force a table realloc to exercise tombstone removal */
180 for (i = 0; i < 20; i++) {
181 sprintf(tmpStr, "entry %d", i);
182 str = (const char*) dvmHashTableLookup(pTab, hash, strdup(tmpStr),
183 (HashCompareFunc) strcmp, true);
184 assert(str != NULL);
185 }
186
187 dvmHashTableFree(pTab);
188 ALOGV("TestHash END");
189
190 return true;
191 }
192
193 #endif /*NDEBUG*/
194