Kad unit tests:

- Port KBSTest from i2p.zzz.kademlia branch
  - Fix RandomTrimmer so it always returns true, so it may be used
    as the trimmer in the unit tests
This commit is contained in:
zzz
2013-11-24 23:39:47 +00:00
parent 1d7eedd463
commit 8699c82614
2 changed files with 128 additions and 10 deletions

View File

@ -8,37 +8,154 @@ package net.i2p.kademlia;
*
*/
import java.util.List;
import junit.framework.TestCase;
import net.i2p.I2PAppContext;
import net.i2p.data.Hash;
import net.i2p.util.Log;
/**
* Test KBucketSet
* Test KBucketSet.
* Newer tests ported from KBSTest in i2p.zzz.kademlia branch
*
* @author comwiz
* @since 0.9.10 moved from net.i2p.router.networkdb.kademlia
*/
public class KBucketSetTest extends TestCase{
private I2PAppContext context;
private KBucketSet<Hash> set;
private Hash usHash;
private Log log;
private static final int K = 8;
private static final int B = 1;
public void setUp(){
context = I2PAppContext.getGlobalContext();
set = new KBucketSet<Hash>(context, Hash.FAKE_HASH, K, B);
log = context.logManager().getLog(KBucketSet.class);
byte[] us = new byte[Hash.HASH_LENGTH];
context.random().nextBytes(us);
usHash = new Hash(us);
// We use the default RandomTrimmer so add() will never fail
set = new KBucketSet<Hash>(context, usHash, K, B);
// tests may be run in any order so prime it
addRandom(1000);
}
public void testRandom(){
for (int i = 0; i < 1000; i++) {
byte val[] = new byte[Hash.HASH_LENGTH];
context.random().nextBytes(val);
assertTrue(set.add(new Hash(val)));
}
}
addRandom(1000);
}
private void addRandom(int count) {
for (int i = 0; i < count; i++) {
byte val[] = new byte[Hash.HASH_LENGTH];
context.random().nextBytes(val);
Hash h = new Hash(val);
// in the highly unlikely chance we randomly generate a hash equal to us
assertTrue(set.add(h) || h.equals(usHash));
}
}
public void testSelf() {
// new implementation will never include myself
assertFalse(set.add(Hash.FAKE_HASH));
assertFalse(set.add(usHash));
}
/** @since 0.9.10 */
public void testConcurrent() {
int count = 2500;
int n = 4;
Thread[] threads = new Thread[n];
for (int i = 0; i < n; i++) {
threads[i] = new RTester(count);
}
for (int i = 0; i < n; i++) {
threads[i].start();
}
for (int i = 0; i < n; i++) {
try {
threads[i].join();
} catch (InterruptedException ie) {}
}
}
/** @since 0.9.10 */
private class RTester extends Thread {
private final int _count;
public RTester(int count) {
_count = count;
}
public void run() {
addRandom(_count);
}
}
/** @since 0.9.10 */
public void testAudit() {
int errors = 0;
for (KBucket<Hash> b : set.getBuckets()) {
for (Hash sds : b.getEntries()) {
int range = set.getRange(sds);
if (range < b.getRangeBegin() || range > b.getRangeEnd()) {
log.error("Hash " + sds + " with range " + range +
" does not belong in " + b);
errors++;
}
}
}
assertTrue(errors == 0);
}
/** @since 0.9.10 */
public void testOrder() {
int bits = Hash.HASH_LENGTH * 8;
int errors = 0;
int lastEnd = -1;
for (KBucket<Hash> b : set.getBuckets()) {
int beg = b.getRangeBegin();
if (beg != lastEnd + 1) {
log.error("Out of order: " + b);
errors++;
}
lastEnd = b.getRangeEnd();
}
if (lastEnd != (bits * (1 << (B-1))) - 1) {
log.error("Out of order: last=" + lastEnd);
errors++;
}
assertTrue(errors == 0);
}
/** @since 0.9.10 */
public void testGenRandom() {
int errors = 0;
for (KBucket b : set.getBuckets()) {
for (int j = 0; j < 4000; j++) {
Hash rand = set.generateRandomKey(b);
int range = set.getRange(rand);
if (range < b.getRangeBegin() || range > b.getRangeEnd()) {
log.error("Generate random key failed range=" + range + " for " + rand + " meant for bucket " + b);
errors++;
}
}
}
assertTrue(errors == 0);
}
/** @since 0.9.10 */
public void testExplore() {
List<Hash> keys = set.getExploreKeys(-1000);
assertTrue(keys.size() > 0);
}
/** @since 0.9.10 */
public void testClosest() {
byte val[] = new byte[Hash.HASH_LENGTH];
for (int i = 0; i < 23; i++) {
context.random().nextBytes(val);
Hash h = new Hash(val);
List<Hash> c = set.getClosest(h, i);
assertTrue(c.size() == i);
}
}
}