]> Sergey Matveev's repositories - btrtrc.git/blobdiff - pex_test.go
Performance improvements to PEX
[btrtrc.git] / pex_test.go
index 161ea1baa67d6b61e33732607a65a9a2b769e1e0..e002362717110360fbb14f4cb895a3fe7a48d345 100644 (file)
@@ -4,6 +4,7 @@ import (
        "net"
        "testing"
 
+       "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/require"
 
        "github.com/anacrolix/dht/v2/krpc"
@@ -114,14 +115,14 @@ var testcases = []struct {
        name  string
        in    *pexState
        arg   int
-       targM *pp.PexMsg
+       targM pp.PexMsg
        targS int
 }{
        {
                name:  "empty",
                in:    &pexState{},
                arg:   0,
-               targM: &pp.PexMsg{},
+               targM: pp.PexMsg{},
                targS: 0,
        },
        {
@@ -135,15 +136,15 @@ var testcases = []struct {
                        },
                },
                arg: 0,
-               targM: &pp.PexMsg{
+               targM: pp.PexMsg{
                        Added: krpc.CompactIPv4NodeAddrs{
-                               nodeAddr(addrs[2]),
-                               nodeAddr(addrs[3]),
+                               mustNodeAddr(addrs[2]),
+                               mustNodeAddr(addrs[3]),
                        },
                        AddedFlags: []pp.PexPeerFlags{f, f},
                        Added6: krpc.CompactIPv6NodeAddrs{
-                               nodeAddr(addrs[0]),
-                               nodeAddr(addrs[1]),
+                               mustNodeAddr(addrs[0]),
+                               mustNodeAddr(addrs[1]),
                        },
                        Added6Flags: []pp.PexPeerFlags{f, f},
                },
@@ -158,12 +159,12 @@ var testcases = []struct {
                                pexEvent{pexDrop, addrs[2], f},
                        },
                },
-               targM: &pp.PexMsg{
+               targM: pp.PexMsg{
                        Dropped: krpc.CompactIPv4NodeAddrs{
-                               nodeAddr(addrs[2]),
+                               mustNodeAddr(addrs[2]),
                        },
                        Dropped6: krpc.CompactIPv6NodeAddrs{
-                               nodeAddr(addrs[0]),
+                               mustNodeAddr(addrs[0]),
                        },
                },
                targS: 2,
@@ -178,9 +179,9 @@ var testcases = []struct {
                                pexEvent{pexDrop, addrs[0], f},
                        },
                },
-               targM: &pp.PexMsg{
+               targM: pp.PexMsg{
                        Added6: krpc.CompactIPv6NodeAddrs{
-                               nodeAddr(addrs[1]),
+                               mustNodeAddr(addrs[1]),
                        },
                        Added6Flags: []pp.PexPeerFlags{f},
                },
@@ -201,14 +202,14 @@ var testcases = []struct {
                                pexEvent{pexDrop, addrs[1], f},
                        },
                },
-               targM: &pp.PexMsg{
+               targM: pp.PexMsg{
                        Added: krpc.CompactIPv4NodeAddrs{
-                               nodeAddr(addrs[2]),
+                               mustNodeAddr(addrs[2]),
                        },
                        AddedFlags: []pp.PexPeerFlags{f},
                        Added6: krpc.CompactIPv6NodeAddrs{
-                               nodeAddr(addrs[0]),
-                               nodeAddr(addrs[1]),
+                               mustNodeAddr(addrs[0]),
+                               mustNodeAddr(addrs[1]),
                        },
                        Added6Flags: []pp.PexPeerFlags{f, f},
                },
@@ -223,9 +224,9 @@ var testcases = []struct {
                                pexEvent{pexAdd, addrs[1], f},
                        },
                },
-               targM: &pp.PexMsg{
+               targM: pp.PexMsg{
                        Added6: krpc.CompactIPv6NodeAddrs{
-                               nodeAddr(addrs[1]),
+                               mustNodeAddr(addrs[1]),
                        },
                        Added6Flags: []pp.PexPeerFlags{f},
                },
@@ -233,13 +234,178 @@ var testcases = []struct {
        },
 }
 
+// Represents the contents of a PexMsg in a way that supports equivalence checking in tests. This is
+// necessary because pexMsgFactory uses maps and so ordering of the resultant PexMsg isn't
+// deterministic. Because the flags are in a different array, we can't just use testify's
+// ElementsMatch because the ordering *does* still matter between an added addr and its flags.
+type comparablePexMsg struct {
+       added, added6     []pexMsgAdded
+       dropped, dropped6 []krpc.NodeAddr
+}
+
+func (me *comparablePexMsg) makeAdded(addrs []krpc.NodeAddr, flags []pp.PexPeerFlags) (ret []pexMsgAdded) {
+       for i, addr := range addrs {
+               ret = append(ret, pexMsgAdded{
+                       NodeAddr:     addr,
+                       PexPeerFlags: flags[i],
+               })
+       }
+       return
+}
+
+// Such Rust-inspired.
+func (me *comparablePexMsg) From(f pp.PexMsg) {
+       me.added = me.makeAdded(f.Added, f.AddedFlags)
+       me.added6 = me.makeAdded(f.Added6, f.Added6Flags)
+       me.dropped = f.Dropped
+       me.dropped6 = f.Dropped6
+}
+
+// For PexMsg created by pexMsgFactory, this is as good as it can get without using data structures
+// in pexMsgFactory that preserve insert ordering.
+func (actual comparablePexMsg) AssertEqual(t *testing.T, expected comparablePexMsg) {
+       assert.ElementsMatch(t, expected.added, actual.added)
+       assert.ElementsMatch(t, expected.added6, actual.added6)
+       assert.ElementsMatch(t, expected.dropped, actual.dropped)
+       assert.ElementsMatch(t, expected.dropped6, actual.dropped6)
+}
+
+func assertPexMsgsEqual(t *testing.T, expected, actual pp.PexMsg) {
+       var ec, ac comparablePexMsg
+       ec.From(expected)
+       ac.From(actual)
+       ac.AssertEqual(t, ec)
+}
+
 func TestPexGenmsg(t *testing.T) {
        for _, tc := range testcases {
                t.Run(tc.name, func(t *testing.T) {
                        s := tc.in
                        m, seen := s.Genmsg(tc.arg)
-                       require.EqualValues(t, tc.targM, m)
+                       assertPexMsgsEqual(t, tc.targM, m)
                        require.EqualValues(t, tc.targS, seen)
                })
        }
 }
+
+func TestPexAdd(t *testing.T) {
+       addrs4 := []krpc.NodeAddr{
+               krpc.NodeAddr{IP: net.IPv4(127, 0, 0, 1), Port: 4747}, // 0
+               krpc.NodeAddr{IP: net.IPv4(127, 0, 0, 1), Port: 4748}, // 1
+               krpc.NodeAddr{IP: net.IPv4(127, 0, 0, 2), Port: 4747}, // 2
+               krpc.NodeAddr{IP: net.IPv4(127, 0, 0, 2), Port: 4748}, // 3
+       }
+       addrs6 := []krpc.NodeAddr{
+               krpc.NodeAddr{IP: net.IPv6loopback, Port: 4747}, // 0
+               krpc.NodeAddr{IP: net.IPv6loopback, Port: 4748}, // 1
+               krpc.NodeAddr{IP: net.IPv6loopback, Port: 4749}, // 2
+               krpc.NodeAddr{IP: net.IPv6loopback, Port: 4750}, // 3
+       }
+       f := pp.PexPrefersEncryption | pp.PexOutgoingConn
+
+       t.Run("ipv4", func(t *testing.T) {
+               addrs := addrs4
+               var m pexMsgFactory
+               m.Drop(addrs[0])
+               m.Add(addrs[1], f)
+               for _, addr := range addrs {
+                       m.Add(addr, f)
+               }
+               targ := pp.PexMsg{
+                       Added: krpc.CompactIPv4NodeAddrs{
+                               addrs[1],
+                               addrs[2],
+                               addrs[3],
+                       },
+                       AddedFlags: []pp.PexPeerFlags{f, f, f},
+               }
+               assertPexMsgsEqual(t, targ, m.PexMsg())
+       })
+       t.Run("ipv6", func(t *testing.T) {
+               addrs := addrs6
+               var m pexMsgFactory
+               m.Drop(addrs[0])
+               m.Add(addrs[1], f)
+               for _, addr := range addrs {
+                       m.Add(addr, f)
+               }
+               targ := pp.PexMsg{
+                       Added6: krpc.CompactIPv6NodeAddrs{
+                               addrs[1],
+                               addrs[2],
+                               addrs[3],
+                       },
+                       Added6Flags: []pp.PexPeerFlags{f, f, f},
+               }
+               assertPexMsgsEqual(t, targ, m.PexMsg())
+       })
+       t.Run("empty", func(t *testing.T) {
+               addr := krpc.NodeAddr{}
+               var xm pexMsgFactory
+               assert.Panics(t, func() { xm.Add(addr, f) })
+               m := xm.PexMsg()
+               require.EqualValues(t, 0, len(m.Added))
+               require.EqualValues(t, 0, len(m.AddedFlags))
+               require.EqualValues(t, 0, len(m.Added6))
+               require.EqualValues(t, 0, len(m.Added6Flags))
+       })
+}
+
+func TestPexDrop(t *testing.T) {
+       addrs4 := []krpc.NodeAddr{
+               krpc.NodeAddr{IP: net.IPv4(127, 0, 0, 1), Port: 4747}, // 0
+               krpc.NodeAddr{IP: net.IPv4(127, 0, 0, 1), Port: 4748}, // 1
+               krpc.NodeAddr{IP: net.IPv4(127, 0, 0, 2), Port: 4747}, // 2
+               krpc.NodeAddr{IP: net.IPv4(127, 0, 0, 2), Port: 4748}, // 3
+       }
+       addrs6 := []krpc.NodeAddr{
+               krpc.NodeAddr{IP: net.IPv6loopback, Port: 4747}, // 0
+               krpc.NodeAddr{IP: net.IPv6loopback, Port: 4748}, // 1
+               krpc.NodeAddr{IP: net.IPv6loopback, Port: 4749}, // 2
+               krpc.NodeAddr{IP: net.IPv6loopback, Port: 4750}, // 3
+       }
+       f := pp.PexPrefersEncryption | pp.PexOutgoingConn
+
+       t.Run("ipv4", func(t *testing.T) {
+               addrs := addrs4
+               var m pexMsgFactory
+               m.Add(addrs[0], f)
+               m.Drop(addrs[1])
+               for _, addr := range addrs {
+                       m.Drop(addr)
+               }
+               targ := pp.PexMsg{
+                       Dropped: krpc.CompactIPv4NodeAddrs{
+                               addrs[1],
+                               addrs[2],
+                               addrs[3],
+                       },
+               }
+               assertPexMsgsEqual(t, targ, m.PexMsg())
+       })
+       t.Run("ipv6", func(t *testing.T) {
+               addrs := addrs6
+               var m pexMsgFactory
+               m.Add(addrs[0], f)
+               m.Drop(addrs[1])
+               for _, addr := range addrs {
+                       m.Drop(addr)
+               }
+               targ := pp.PexMsg{
+                       Dropped6: krpc.CompactIPv6NodeAddrs{
+                               addrs[1],
+                               addrs[2],
+                               addrs[3],
+                       },
+               }
+               assertPexMsgsEqual(t, targ, m.PexMsg())
+       })
+       t.Run("empty", func(t *testing.T) {
+               addr := krpc.NodeAddr{}
+               var xm pexMsgFactory
+               require.Panics(t, func() { xm.Drop(addr) })
+               m := xm.PexMsg()
+               require.EqualValues(t, 0, len(m.Dropped))
+               require.EqualValues(t, 0, len(m.Dropped6))
+       })
+}