Engine interface with Wireguard specific implementation.
diff --git a/core/vpn/engine/wireguard_test.go b/core/vpn/engine/wireguard_test.go
new file mode 100644
index 0000000..39488e3
--- /dev/null
+++ b/core/vpn/engine/wireguard_test.go
@@ -0,0 +1,119 @@
+package engine
+
+import (
+ "fmt"
+ "log"
+ "testing"
+
+ "github.com/giolekva/pcloud/core/vpn/types"
+
+ "inet.af/netaddr"
+ "tailscale.com/ipn/ipnstate"
+)
+
+type node struct {
+ ip netaddr.IP
+ privKey types.PrivateKey
+ node types.Node
+ peers []types.Node
+ e Engine
+}
+
+func newNode(ip string, localPort uint16) (n *node, err error) {
+ n = &node{
+ ip: netaddr.MustParseIP(ip),
+ privKey: types.NewPrivateKey(),
+ }
+ if n.e, err = NewFakeWireguardEngine(localPort, n.privKey); err != nil {
+ return
+ }
+ n.node = types.Node{
+ PublicKey: n.privKey.Public(),
+ DiscoKey: n.e.DiscoKey(),
+ DiscoEndpoint: n.e.DiscoEndpoint(),
+ IPPort: netaddr.IPPort{
+ IP: netaddr.IPv4(127, 0, 0, 1),
+ Port: localPort,
+ },
+ VPNIP: netaddr.MustParseIP(ip),
+ }
+ return
+}
+
+func (n *node) addPeer(x types.Node) {
+ n.peers = append(n.peers, x)
+}
+
+func (n *node) configure() error {
+ return n.e.Configure(&types.NetworkMap{n.node, n.peers})
+}
+
+func (n *node) ping(ip string, ch chan<- *ipnstate.PingResult) {
+ n.e.Ping(netaddr.MustParseIP(ip), func(p *ipnstate.PingResult) {
+ ch <- p
+ })
+}
+
+func TestTwoPeers(t *testing.T) {
+ var a, b *node
+ var err error
+ if a, err = newNode("10.0.0.1", 1234); err != nil {
+ t.Fatal(err)
+ }
+ if b, err = newNode("10.0.0.2", 1235); err != nil {
+ t.Fatal(err)
+ }
+ a.addPeer(b.node)
+ b.addPeer(a.node)
+ if err := a.configure(); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.configure(); err != nil {
+ t.Fatal(err)
+ }
+ ping := make(chan *ipnstate.PingResult, 0)
+ a.ping("10.0.0.2", ping)
+ b.ping("10.0.0.1", ping)
+ for i := 0; i < 2; i++ {
+ p := <-ping
+ if p.Err != "" {
+ t.Error(p.Err)
+ }
+ log.Printf("Ping received: %+v\n", p)
+ }
+}
+
+func TestTenPeers(t *testing.T) {
+ n := 10
+ nodes := make([]*node, n)
+ ping := make(chan *ipnstate.PingResult, 0)
+ for i := 0; i < n; i++ {
+ ip := fmt.Sprintf("10.0.0.%d", i+1)
+ localPort := uint16(i + 4321)
+ var err error
+ if nodes[i], err = newNode(ip, localPort); err != nil {
+ t.Fatal(err)
+ }
+ for j := 0; j < i; j++ {
+ nodes[i].addPeer(nodes[j].node)
+ nodes[j].addPeer(nodes[i].node)
+ }
+ }
+ for i := 0; i < n; i++ {
+ if err := nodes[i].configure(); err != nil {
+ t.Fatal(err)
+ }
+ for j := 0; j < i; j++ {
+ nodes[i].ping(nodes[j].ip.String(), ping)
+ nodes[j].ping(nodes[i].ip.String(), ping)
+ }
+
+ }
+ for i := 0; i < n*(n-1); i++ {
+ p := <-ping
+ if p.Err != "" {
+ t.Error(p.Err)
+ }
+ log.Printf("Ping received: %+v\n", p)
+ }
+}