• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         LOGE("TestHash foreach test failed\n");
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         LOGE("TestHash iterator test failed\n");
71         assert(false);
72     }
73 }
74 
75 /*
76  * Some quick hash table tests.
77  */
dvmTestHash(void)78 bool dvmTestHash(void)
79 {
80     HashTable* pTab;
81     char tmpStr[64];
82     const char* str;
83     u4 hash;
84     int i;
85 
86     LOGV("TestHash BEGIN\n");
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             LOGE("TestHash: failure: could not find '%s'\n", 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         LOGE("TestHash found nonexistent string (improper add?)\n");
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     char* str1;
145     str1 = dvmHashTableLookup(pTab, hash, strdup("one"),
146             (HashCompareFunc) strcmp, true);
147     assert(str1 != NULL);
148     str = dvmHashTableLookup(pTab, hash, strdup("two"),
149             (HashCompareFunc) strcmp, true);
150 
151     /* remove the first one */
152     if (!dvmHashTableRemove(pTab, hash, str1))
153         LOGE("TestHash failed to delete item\n");
154     else
155         free(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         LOGE("TestHash wrong number of entries (%d)\n", count);
167     }
168 
169     /* see if we can find them */
170     str = dvmHashTableLookup(pTab, hash, "one", (HashCompareFunc) strcmp,false);
171     if (str != NULL)
172         LOGE("TestHash deleted entry has returned!");
173     str = dvmHashTableLookup(pTab, hash, "two", (HashCompareFunc) strcmp,false);
174     if (str == NULL)
175         LOGE("TestHash entry vanished\n");
176 
177     /* force a table realloc to exercise tombstone removal */
178     for (i = 0; i < 20; i++) {
179         sprintf(tmpStr, "entry %d", i);
180         str = (const char*) dvmHashTableLookup(pTab, hash, strdup(tmpStr),
181                 (HashCompareFunc) strcmp, true);
182         assert(str != NULL);
183     }
184 
185     dvmHashTableFree(pTab);
186     LOGV("TestHash END\n");
187 
188     return true;
189 }
190 
191 #endif /*NDEBUG*/
192