forked from I2P_Developers/i2p.i2p
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:
@@ -26,6 +26,7 @@ public class RandomTrimmer<T extends SimpleDataStructure> implements KBucketTrim
|
|||||||
if (sz < _max)
|
if (sz < _max)
|
||||||
return true;
|
return true;
|
||||||
T toRemove = e.get(_ctx.random().nextInt(sz));
|
T toRemove = e.get(_ctx.random().nextInt(sz));
|
||||||
return kbucket.remove(toRemove);
|
kbucket.remove(toRemove);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,37 +8,154 @@ package net.i2p.kademlia;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.data.Hash;
|
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
|
* @author comwiz
|
||||||
|
* @since 0.9.10 moved from net.i2p.router.networkdb.kademlia
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class KBucketSetTest extends TestCase{
|
public class KBucketSetTest extends TestCase{
|
||||||
private I2PAppContext context;
|
private I2PAppContext context;
|
||||||
private KBucketSet<Hash> set;
|
private KBucketSet<Hash> set;
|
||||||
|
private Hash usHash;
|
||||||
|
private Log log;
|
||||||
private static final int K = 8;
|
private static final int K = 8;
|
||||||
private static final int B = 1;
|
private static final int B = 1;
|
||||||
|
|
||||||
public void setUp(){
|
public void setUp(){
|
||||||
context = I2PAppContext.getGlobalContext();
|
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(){
|
public void testRandom(){
|
||||||
for (int i = 0; i < 1000; i++) {
|
addRandom(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addRandom(int count) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
byte val[] = new byte[Hash.HASH_LENGTH];
|
byte val[] = new byte[Hash.HASH_LENGTH];
|
||||||
context.random().nextBytes(val);
|
context.random().nextBytes(val);
|
||||||
assertTrue(set.add(new Hash(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() {
|
public void testSelf() {
|
||||||
// new implementation will never include myself
|
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user