wip: migrate to mono-repo. SPN has already been moved to spn/
This commit is contained in:
279
spn/navigator/map_test.go
Normal file
279
spn/navigator/map_test.go
Normal file
@@ -0,0 +1,279 @@
|
||||
package navigator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/brianvoe/gofakeit"
|
||||
|
||||
"github.com/safing/jess/lhash"
|
||||
"github.com/safing/portmaster/service/intel/geoip"
|
||||
"github.com/safing/portmaster/spn/hub"
|
||||
)
|
||||
|
||||
var (
|
||||
fakeLock sync.Mutex
|
||||
|
||||
defaultMapCreate sync.Once
|
||||
defaultMap *Map
|
||||
)
|
||||
|
||||
func getDefaultTestMap() *Map {
|
||||
defaultMapCreate.Do(func() {
|
||||
defaultMap = createRandomTestMap(1, 200)
|
||||
})
|
||||
return defaultMap
|
||||
}
|
||||
|
||||
func TestRandomMapCreation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
m := getDefaultTestMap()
|
||||
|
||||
fmt.Println("All Pins:")
|
||||
for _, pin := range m.all {
|
||||
fmt.Printf("%s: %s %s\n", pin, pin.Hub.Info.IPv4, pin.Hub.Info.IPv6)
|
||||
}
|
||||
|
||||
// Print stats
|
||||
fmt.Printf("\n%s\n", m.Stats())
|
||||
|
||||
// Print home
|
||||
fmt.Printf("Selected Home Hub: %s\n", m.home)
|
||||
}
|
||||
|
||||
func createRandomTestMap(seed int64, size int) *Map {
|
||||
fakeLock.Lock()
|
||||
defer fakeLock.Unlock()
|
||||
|
||||
// Seed with parameter to make it reproducible.
|
||||
gofakeit.Seed(seed)
|
||||
|
||||
// Enforce minimum size.
|
||||
if size < 10 {
|
||||
size = 10
|
||||
}
|
||||
|
||||
// Create Hub list.
|
||||
var hubs []*hub.Hub
|
||||
|
||||
// Create Intel data structure.
|
||||
mapIntel := &hub.Intel{
|
||||
Hubs: make(map[string]*hub.HubIntel),
|
||||
}
|
||||
|
||||
// Define periodic values.
|
||||
var currentGroup string
|
||||
|
||||
// Create [size] fake Hubs.
|
||||
for i := 0; i < size; i++ {
|
||||
// Change group every 5 Hubs.
|
||||
if i%5 == 0 {
|
||||
currentGroup = gofakeit.Username()
|
||||
}
|
||||
|
||||
// Create new fake Hub and add to the list.
|
||||
h := createFakeHub(currentGroup, true, mapIntel)
|
||||
hubs = append(hubs, h)
|
||||
}
|
||||
|
||||
// Fake three superseeded Hubs.
|
||||
for i := 0; i < 3; i++ {
|
||||
h := hubs[size-1-i]
|
||||
|
||||
// Set FirstSeen in the past and copy an IP address of an existing Hub.
|
||||
h.FirstSeen = time.Now().Add(-1 * time.Hour)
|
||||
if i%2 == 0 {
|
||||
h.Info.IPv4 = hubs[i].Info.IPv4
|
||||
} else {
|
||||
h.Info.IPv6 = hubs[i].Info.IPv6
|
||||
}
|
||||
}
|
||||
|
||||
// Create Lanes between Hubs in order to create the network.
|
||||
totalConnections := size * 10
|
||||
for i := 0; i < totalConnections; i++ {
|
||||
// Get new random indexes.
|
||||
indexA := gofakeit.Number(0, size-1)
|
||||
indexB := gofakeit.Number(0, size-1)
|
||||
if indexA == indexB {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get Hubs and check if they are already connected.
|
||||
hubA := hubs[indexA]
|
||||
hubB := hubs[indexB]
|
||||
if hubA.GetLaneTo(hubB.ID) != nil {
|
||||
// already connected
|
||||
continue
|
||||
}
|
||||
if hubB.GetLaneTo(hubA.ID) != nil {
|
||||
// already connected
|
||||
continue
|
||||
}
|
||||
|
||||
// Create connections.
|
||||
_ = hubA.AddLane(createLane(hubB.ID))
|
||||
// Add the second connection in 99% of cases.
|
||||
// If this is missing, the Pins should not show up as connected.
|
||||
if gofakeit.Number(0, 100) != 0 {
|
||||
_ = hubB.AddLane(createLane(hubA.ID))
|
||||
}
|
||||
}
|
||||
|
||||
// Parse constructed intel data
|
||||
err := mapIntel.ParseAdvisories()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create map and add Pins.
|
||||
m := NewMap(fmt.Sprintf("Test-Map-%d", seed), true)
|
||||
m.intel = mapIntel
|
||||
for _, h := range hubs {
|
||||
m.UpdateHub(h)
|
||||
}
|
||||
|
||||
// Fake communication error with three Hubs.
|
||||
var i int
|
||||
for _, pin := range m.all {
|
||||
pin.MarkAsFailingFor(1 * time.Hour)
|
||||
pin.addStates(StateFailing)
|
||||
|
||||
if i++; i >= 3 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Set a Home Hub.
|
||||
findFakeHomeHub(m)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func createFakeHub(group string, randomFailes bool, mapIntel *hub.Intel) *hub.Hub {
|
||||
// Create fake Hub ID.
|
||||
idSrc := gofakeit.Password(true, true, true, true, true, 64)
|
||||
id := lhash.Digest(lhash.BLAKE2b_256, []byte(idSrc)).Base58()
|
||||
ip4, _ := createGoodIP(true)
|
||||
ip6, _ := createGoodIP(false)
|
||||
|
||||
// Create and return new fake Hub.
|
||||
h := &hub.Hub{
|
||||
ID: id,
|
||||
Info: &hub.Announcement{
|
||||
ID: id,
|
||||
Timestamp: time.Now().Unix(),
|
||||
Name: gofakeit.Username(),
|
||||
Group: group,
|
||||
// ContactAddress // TODO
|
||||
// ContactService // TODO
|
||||
// Hosters []string // TODO
|
||||
// Datacenter string // TODO
|
||||
IPv4: ip4,
|
||||
IPv6: ip6,
|
||||
},
|
||||
Status: &hub.Status{
|
||||
Timestamp: time.Now().Unix(),
|
||||
Keys: map[string]*hub.Key{
|
||||
"a": {
|
||||
Expires: time.Now().Add(48 * time.Hour).Unix(),
|
||||
},
|
||||
},
|
||||
Load: gofakeit.Number(10, 100),
|
||||
},
|
||||
Measurements: hub.NewMeasurements(),
|
||||
FirstSeen: time.Now(),
|
||||
}
|
||||
h.Measurements.Latency = createLatency()
|
||||
h.Measurements.Capacity = createCapacity()
|
||||
h.Measurements.CalculatedCost = CalculateLaneCost(
|
||||
h.Measurements.Latency,
|
||||
h.Measurements.Capacity,
|
||||
)
|
||||
|
||||
// Return if not failures of any kind should be simulated.
|
||||
if !randomFailes {
|
||||
return h
|
||||
}
|
||||
|
||||
// Set hub-based states.
|
||||
if gofakeit.Number(0, 100) == 0 {
|
||||
// Fake Info message error.
|
||||
h.InvalidInfo = true
|
||||
}
|
||||
if gofakeit.Number(0, 100) == 0 {
|
||||
// Fake Status message error.
|
||||
h.InvalidStatus = true
|
||||
}
|
||||
if gofakeit.Number(0, 100) == 0 {
|
||||
// Fake expired exchange keys.
|
||||
for _, key := range h.Status.Keys {
|
||||
key.Expires = time.Now().Add(-1 * time.Hour).Unix()
|
||||
}
|
||||
}
|
||||
|
||||
// Return if not failures of any kind should be simulated.
|
||||
if mapIntel == nil {
|
||||
return h
|
||||
}
|
||||
|
||||
// Set advisory-based states.
|
||||
if gofakeit.Number(0, 10) == 0 {
|
||||
// Make Trusted State
|
||||
mapIntel.Hubs[h.ID] = &hub.HubIntel{
|
||||
Trusted: true,
|
||||
}
|
||||
}
|
||||
if gofakeit.Number(0, 100) == 0 {
|
||||
// Discourage any usage.
|
||||
mapIntel.HubAdvisory = append(mapIntel.HubAdvisory, "- "+h.Info.IPv4.String())
|
||||
}
|
||||
if gofakeit.Number(0, 100) == 0 {
|
||||
// Discourage Home Hub usage.
|
||||
mapIntel.HomeHubAdvisory = append(mapIntel.HomeHubAdvisory, "- "+h.Info.IPv4.String())
|
||||
}
|
||||
if gofakeit.Number(0, 100) == 0 {
|
||||
// Discourage Destination Hub usage.
|
||||
mapIntel.DestinationHubAdvisory = append(mapIntel.DestinationHubAdvisory, "- "+h.Info.IPv4.String())
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func createGoodIP(v4 bool) (net.IP, *geoip.Location) {
|
||||
var candidate net.IP
|
||||
for i := 0; i < 100; i++ {
|
||||
if v4 {
|
||||
candidate = net.ParseIP(gofakeit.IPv4Address())
|
||||
} else {
|
||||
candidate = net.ParseIP(gofakeit.IPv6Address())
|
||||
}
|
||||
loc, err := geoip.GetLocation(candidate)
|
||||
if err == nil && loc.Coordinates.Latitude != 0 {
|
||||
return candidate, loc
|
||||
}
|
||||
}
|
||||
return candidate, nil
|
||||
}
|
||||
|
||||
func createLane(toHubID string) *hub.Lane {
|
||||
return &hub.Lane{
|
||||
ID: toHubID,
|
||||
Latency: createLatency(),
|
||||
Capacity: createCapacity(),
|
||||
}
|
||||
}
|
||||
|
||||
func createLatency() time.Duration {
|
||||
// Return a value between 10ms and 100ms.
|
||||
return time.Duration(gofakeit.Float64Range(10, 100) * float64(time.Millisecond))
|
||||
}
|
||||
|
||||
func createCapacity() int {
|
||||
// Return a value between 10Mbit/s and 1Gbit/s.
|
||||
return gofakeit.Number(10000000, 1000000000)
|
||||
}
|
||||
Reference in New Issue
Block a user