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:
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user