246 lines
6.3 KiB
Go
246 lines
6.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
kademlia "gitlab.lrz.de/netintum/teaching/p2psec_projects_2024/DHT-6/pkg"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func startServer(config *kademlia.Config) *kademlia.DHT {
|
|
dht := kademlia.NewDHT(config)
|
|
|
|
go initializeAPIServer(config, dht)
|
|
go initializeP2PServer(config, dht)
|
|
return dht
|
|
}
|
|
|
|
func TestBasicStartAPI(t *testing.T) {
|
|
|
|
config := &kademlia.Config{
|
|
P2PPort: 6001,
|
|
APIPort: 7001,
|
|
P2PAddress: "127.0.0.2",
|
|
APIAddress: "127.0.0.2",
|
|
KeyFile: "certs/key.pem",
|
|
CertFile: "certs/cert.pem",
|
|
PrefixLength: 5,
|
|
RepublishInterval: 3600,
|
|
}
|
|
startServer(config)
|
|
|
|
time.Sleep(1 * time.Second)
|
|
var key [32]byte
|
|
value := []byte("Hello World")
|
|
packet := kademlia.SerialisePutPacket(&kademlia.DHTPutPacket{
|
|
TTL: 20,
|
|
Replication: 20,
|
|
Key: key,
|
|
Value: value,
|
|
})
|
|
|
|
conn, err := kademlia.ConnectToApi("127.0.0.2", 7001)
|
|
if err != nil {
|
|
t.Fatalf("Failed to connect %v", err)
|
|
}
|
|
conn.Write(packet)
|
|
conn.Close()
|
|
packet = kademlia.SerialiseGetPacket(&kademlia.DHTGetPacket{Key: key})
|
|
|
|
conn, err = kademlia.ConnectToApi("127.0.0.2", 7001)
|
|
if err != nil {
|
|
t.Fatalf("Failed to connect %v", err)
|
|
}
|
|
|
|
conn.Write(packet)
|
|
response := make([]byte, 100)
|
|
n, _ := conn.Read(response)
|
|
t.Logf("Response: %v Num: %d", response, n)
|
|
|
|
}
|
|
|
|
/*
|
|
Testing whether or not the boostrapping process works as intended. By running the second node configured with
|
|
the first as boostrapper, they both should appear in each others routing tables.
|
|
*/
|
|
func TestBoostrap(t *testing.T) {
|
|
config1 := &kademlia.Config{
|
|
P2PPort: 6001,
|
|
APIPort: 7001,
|
|
P2PAddress: "127.0.0.2",
|
|
APIAddress: "127.0.0.2",
|
|
KeyFile: "certs/key.pem",
|
|
CertFile: "certs/cert.pem",
|
|
}
|
|
|
|
config2 := &kademlia.Config{
|
|
P2PPort: 6001,
|
|
APIPort: 7001,
|
|
P2PAddress: "127.0.0.1",
|
|
APIAddress: "127.0.0.1",
|
|
Bootstrapper: "127.0.0.2",
|
|
BootstrapperPort: 6001,
|
|
BootstrapperCert: "certs/cert.pem",
|
|
KeyFile: "certs/key1.pem",
|
|
CertFile: "certs/cert1.pem",
|
|
}
|
|
|
|
dht := startServer(config1)
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
dht2 := startServer(config2)
|
|
time.Sleep(100 * time.Millisecond)
|
|
if !kademlia.ContainsNode(*dht.RoutingTable.FindClosest(dht2.SelfNode.NodeID, 10), dht2.SelfNode) {
|
|
t.Fatalf("Boostrapping failed, node1 did not add node2 to table")
|
|
}
|
|
if !kademlia.ContainsNode(*dht2.RoutingTable.FindClosest(dht.SelfNode.NodeID, 10), dht2.SelfNode) {
|
|
t.Fatalf("Boostrapping failed, node2 did not add node1 to table")
|
|
}
|
|
}
|
|
|
|
/*
|
|
This test covers most of the DHTs functionality. One node acts as bootstrapper for the others,
|
|
two values are stored with different replication counts. It is tested whether finding these values works from
|
|
any node in the network and whether the replication works correctly.
|
|
*/
|
|
func TestStoreReceiveReplication(t *testing.T) {
|
|
dhts := make([]kademlia.DHT, 0)
|
|
for i := 2; i < 40; i++ {
|
|
config := &kademlia.Config{
|
|
P2PPort: 7001,
|
|
APIPort: 6001,
|
|
P2PAddress: "127.0.0." + strconv.Itoa(i),
|
|
APIAddress: "127.0.0." + strconv.Itoa(i),
|
|
Bootstrapper: "127.0.0.2",
|
|
BootstrapperPort: 7001,
|
|
BootstrapperCert: "certs/cert2.pem",
|
|
KeyFile: fmt.Sprintf("certs/key%d.pem", i),
|
|
CertFile: fmt.Sprintf("certs/cert%d.pem", i),
|
|
PrefixLength: 5,
|
|
RepublishInterval: 3600 * time.Second,
|
|
}
|
|
if i == 2 {
|
|
config.Bootstrapper = ""
|
|
}
|
|
time.Sleep(100 * time.Millisecond)
|
|
dht := startServer(config)
|
|
dhts = append(dhts, *dht)
|
|
}
|
|
time.Sleep(100 * time.Millisecond)
|
|
var key, key2 [32]byte
|
|
key2[0] = 1
|
|
value := []byte("Hello World")
|
|
packet := kademlia.SerialisePutPacket(&kademlia.DHTPutPacket{
|
|
TTL: 200,
|
|
Replication: 20,
|
|
Key: key,
|
|
Value: value,
|
|
})
|
|
conn, err := kademlia.ConnectToApi("127.0.0.2", 6001)
|
|
if err != nil {
|
|
t.Fatalf("Failed to connect %v", err)
|
|
}
|
|
conn.Write(packet)
|
|
conn.Close()
|
|
|
|
conn, err = kademlia.ConnectToApi("127.0.0.2", 6001)
|
|
packet = kademlia.SerialisePutPacket(&kademlia.DHTPutPacket{
|
|
TTL: 200,
|
|
Replication: 5,
|
|
Key: key2,
|
|
Value: value,
|
|
})
|
|
conn.Write(packet)
|
|
conn.Close()
|
|
time.Sleep(3 * time.Second)
|
|
|
|
for n, client := range dhts {
|
|
v, ex := client.Get(key)
|
|
|
|
if ex {
|
|
for i, b := range v {
|
|
if value[i] != b {
|
|
t.Fatalf("Incorrect value found by node %d", n)
|
|
}
|
|
}
|
|
t.Logf("found key one at node %d", n)
|
|
} else {
|
|
t.Fatalf("Value coud not be found by node %d", n)
|
|
}
|
|
}
|
|
c1, c2 := 0, 0
|
|
for _, client := range dhts {
|
|
_, e := client.Storage.GetValue(key)
|
|
if e {
|
|
c1++
|
|
}
|
|
_, e = client.Storage.GetValue(key2)
|
|
if e {
|
|
c2++
|
|
}
|
|
}
|
|
t.Logf("Key 1 stored %d times and Key 2 stored %d times", c1, c2)
|
|
}
|
|
|
|
func TestExpireRepublish(t *testing.T) {
|
|
configs := make([]kademlia.Config, 0)
|
|
for i := 2; i < 4; i++ {
|
|
config := &kademlia.Config{
|
|
P2PPort: 7001,
|
|
APIPort: 6001,
|
|
P2PAddress: "127.0.0." + strconv.Itoa(i),
|
|
APIAddress: "127.0.0." + strconv.Itoa(i),
|
|
Bootstrapper: "127.0.0.2",
|
|
BootstrapperPort: 7001,
|
|
BootstrapperCert: "certs/cert2.pem",
|
|
KeyFile: fmt.Sprintf("certs/key%d.pem", i),
|
|
CertFile: fmt.Sprintf("certs/cert%d.pem", i),
|
|
PrefixLength: 5,
|
|
RepublishInterval: 10 * time.Second,
|
|
}
|
|
if i == 2 {
|
|
config.Bootstrapper = ""
|
|
}
|
|
time.Sleep(100 * time.Millisecond)
|
|
configs = append(configs, *config)
|
|
}
|
|
configs[0].Bootstrapper = ""
|
|
dht1 := startServer(&configs[0])
|
|
|
|
var key [32]byte
|
|
var key2 [32]byte
|
|
key2[0] = 1
|
|
value := []byte("Hello World")
|
|
dht1.Store(key, value, 5, 10)
|
|
dht1.Store(key2, value, 1000, 10)
|
|
|
|
dht2 := startServer(&configs[1])
|
|
time.Sleep(100 * time.Millisecond)
|
|
if _, e := dht1.Storage.GetValue(key); !e {
|
|
t.Fatal("Key not stored!")
|
|
}
|
|
if _, e := dht1.Storage.GetValue(key2); !e {
|
|
t.Fatal("Key not stored!")
|
|
}
|
|
if _, e := dht2.Storage.GetValue(key2); e {
|
|
t.Fatal("Key should not be present yet!")
|
|
}
|
|
|
|
// Trigger republishing
|
|
time.Sleep(10 * time.Second)
|
|
kademlia.Ping(dht1.SelfNode, dht2.SelfNode)
|
|
time.Sleep(1 * time.Second)
|
|
|
|
if _, e := dht1.Storage.GetValue(key); e {
|
|
t.Fatal("Key should have been deleted!")
|
|
}
|
|
if _, e := dht1.Storage.GetValue(key2); !e {
|
|
t.Fatal("Key not stored!")
|
|
}
|
|
if _, e := dht2.Storage.GetValue(key2); !e {
|
|
t.Fatal("Key should have been republished!")
|
|
}
|
|
|
|
}
|