Unit Test of Dalvik Virtual Machine hash table
Source code in DVM
Dalvik/Vm/test/testhash. cpp is a built-in ut test case of DVM. Its implementation is intuitive. Let's analyze it briefly:
Test cases:
All tests are performed in the dvmtesthash () function. The test procedure is as follows.
The first round is basic API testing, including creating, inserting, searching, traversing, and releasing hash tables.
Create a hash table for the first test:
Logv ("testhash begin ");
// Rambo: allocate 12 but insert more, to let hash to extend
PTAB = dvmhashtablecreate (dvmhashsize (12), free );
If (PTAB = NULL)
Return false;
Add a hash unit to the table. The unit value is the string "entry xx" XX, which is an integer from 1 to knumtestentries. The Unit Key is calculated using the dvmcomputeutf8hash function.
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 );
Then, you can search for all the units you just added:
/* 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 ){
LogE ("testhash: Failure: cocould not find '% S'", tmpstr );
/* Return false */
}
}
Then try to search for a nonexistent unit:
/* 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 {
LogE ("testhash found nonexistent string (improper add ?) ");
}
Call dumpforeach (PTAB) to test the dvmhashforeach function.
Static void dumpforeach (hashtable * PTAB)
{
Int COUNT = 0;
// Printf ("print from foreach: \ n ");
Dvmhashforeach (PTAB, printfunc, & COUNT );
If (count! = Knumtestentries ){
LogE ("testhash foreach test failed ");
Assert (false );
}
}
The input traversal execution function is printfunc. It traverses a hash table and simply increases the number of units:
Static int printfunc (void * data, void * Arg)
{
// Printf ("'% s' \ n", (const char *) data );
// (Shocould verify strings)
Int * COUNT = (int *) ARG;
(* Count) ++;
Return 0;
}
Dumpforeach is used to test whether the number of units is correct after dvmhashforeach traversal.
Call dumpiterator (PTAB) to check whether the hash table traversal tool works normally. The implementation is to simply traverse the Left and Right units and check whether the number of units is correct.
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 );
// (Shocould verify strings)
Count ++;
}
If (count! = Knumtestentries ){
LogE ("testhash iterator test failed ");
Assert (false );
}
}
Call dvmhashtablefree to release the hash table. The first round of test is complete.
/* Make sure they all get freed */
Dvmhashtablefree (PTAB)
The second round of tests is used to test "unconventional" scenarios:
First, create a hash table with the initial capacity of only two units:
PTAB = dvmhashtablecreate (dvmhashsize (2), free );
If (PTAB = NULL)
Return false;
Then, try to insert two units with the same hash value!
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 );
Then, remove the first unit:
/* Remove the first one */
If (! Dvmhashtableremove (PTAB, hash, (void *) str1 ))
LogE ("testhash failed to delete item ");
Else
Free (void *) str1); // "Remove" doesn't call the free func
Check whether there is only one unit in the hash table:
/* Make sure iterator doesn't supported ded deleted entries */
Int COUNT = 0;
Hashiter ITER;
For (dvmhashiterbegin (PTAB, & ITER );! Dvmhashiterdone (& ITER );
Dvmhashiternext (& ITER ))
{
Count ++;
}
If (count! = 1 ){
LogE ("testhash wrong number of entries (% d)", count );
}
Then check that the removed unit cannot be searched, but the second unit can:
/* See if we can find them */
STR = (const char *) dvmhashtablelookup (PTAB, hash, (void *) "one ",
(Hashcomparefunc) strcmp, false );
If (STR! = NULL)
LogE ("testhash deleted entry has returned! ");
STR = (const char *) dvmhashtablelookup (PTAB, hash, (void *) "two ",
(Hashcomparefunc) strcmp, false );
If (STR = NULL)
LogE ("testhash entry vanished ");
Next, check and insert 17 units into the hash table to check whether the automatic expansion of the hash table is correct:
/* 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 );
}
Finally, release the hash table. The test is complete.
Dvmhashtablefree (PTAB );
Logv ("testhash end ");
Return true
Test execution
Hash ut can be executed during DVM initialization, provided that the debug switch is Enabled:
// Dalvik/Vm/init. cpp
STD: String dvmstartup (INT argc, const char * const argv [],
Bool ignoreunrecognized, jnienv * penv)
{
...
# Ifndef ndebug
// Rambo: perform quick UT
If (! Dvmtesthash ())
LogE ("dvmtesthash failed ");
...
# Endif
...
}
To enable the debug switch, we can specify
// Dalvik/Vm/DVM. mk
# Make a debugging version when building the simulator (if not told
# Otherwise) And when explicitly asked.
Dvm_make_debug_vm: = false
Ifneq ($ (Strip $ (debug_dalvik_vm )),)
Dvm_make_debug_vm: =$ (debug_dalvik_vm)
Endif
Ifeq ($ (dvm_make_debug_vm), true)
...
Local_cflags + =-undebug-ddebug = 1-dlog_ndebug = 1-dwith_dalvik_assert
Else
...
Endif #! Dvm_make_debug_vm
For more information about DVM compiling scripts, see
Dalvik
VM make file config and source tree.