func TestPingMessage(t *testing.T) { d := newDefaultDaemon() defer shutdown(d) p := d.Pool.Pool m := &PingMessage{} testSimpleMessageHandler(t, d, m) m.c = messageContext(addr) go p.ConnectionWriteLoop(m.c.Conn) defer m.c.Conn.Close() assert.NotPanics(t, func() { m.Process(d) }) // A pong message should have been sent wait() assert.Equal(t, len(p.SendResults), 1) if len(p.SendResults) == 0 { t.Fatalf("SendResults empty, would block") } sr := <-p.SendResults assert.Equal(t, sr.Connection, m.c.Conn) assert.Nil(t, sr.Error) _, ok := sr.Message.(*PongMessage) assert.True(t, ok) assert.False(t, m.c.Conn.LastSent.IsZero()) // Test serialization mm := PingMessage{} b := encoder.Serialize(mm) m2 := PingMessage{} assert.Nil(t, encoder.DeserializeRaw(b, &m2)) assert.Equal(t, mm, m2) gnet.EraseMessages() }
func TestOnDisconnect(t *testing.T) { gnet.EraseMessages() d := newDefaultDaemon() c := gnetConnection(addr) var mirror uint32 = 100 // Not blacklistable reason := gnet.DisconnectWriteFailed setupTestOnDisconnect(d, c, mirror) assert.NotPanics(t, func() { d.onGnetDisconnect(c, reason) }) // Should not be in blacklist assert.Equal(t, len(d.Peers.Peers.Blacklist), 0) // Should no longer be in OutgoingConnections assert.Equal(t, len(d.OutgoingConnections), 0) // Should no longer be in d.ExpectingIntroductions assert.Equal(t, len(d.ExpectingIntroductions), 0) // Should be removed from the mirror, and the mirror dict for this ip // should be removed assert.Equal(t, len(d.mirrorConnections), 0) assert.Equal(t, len(d.ConnectionMirrors), 0) // Blacklistable reason = DisconnectIntroductionTimeout setupTestOnDisconnect(d, c, mirror) assert.NotPanics(t, func() { d.onGnetDisconnect(c, reason) }) assert.Equal(t, len(d.Peers.Peers.Blacklist), 1) assert.NotNil(t, d.Peers.Peers.Blacklist[addr]) // Should be in blacklist assert.Equal(t, len(d.Peers.Peers.Blacklist), 1) assert.NotNil(t, d.Peers.Peers.Blacklist[addr]) // Should no longer be in OutgoingConnections assert.Equal(t, len(d.OutgoingConnections), 0) // Should no longer be in d.ExpectingIntroductions assert.Equal(t, len(d.ExpectingIntroductions), 0) // Should be removed from the mirror, and the mirror dict for this ip // should be removed assert.Equal(t, len(d.mirrorConnections), 0) assert.Equal(t, len(d.ConnectionMirrors), 0) // Cleanup delete(d.Peers.Peers.Blacklist, addr) // d.mirrorConnections should retain a submap if there are other ports // inside reason = gnet.DisconnectWriteFailed setupTestOnDisconnect(d, c, mirror) d.mirrorConnections[mirror][strings.Split(addrb, ":")[0]] = addrPort assert.NotPanics(t, func() { d.onGnetDisconnect(c, reason) }) // Should not be in blacklist assert.Equal(t, len(d.Peers.Peers.Blacklist), 0) // Should no longer be in OutgoingConnections assert.Equal(t, len(d.OutgoingConnections), 0) // Should no longer be in d.ExpectingIntroductions assert.Equal(t, len(d.ExpectingIntroductions), 0) // Should be removed from the mirror, and the mirror dict for this ip // should be removed assert.Equal(t, len(d.mirrorConnections), 1) assert.Equal(t, len(d.mirrorConnections[mirror]), 1) assert.Equal(t, len(d.ConnectionMirrors), 0) shutdown(d) }
func TestGivePeersMessage(t *testing.T) { d := newDefaultDaemon() defer shutdown(d) addrs := []string{addr, addrb, "7"} peers := make([]*pex.Peer, 3) for i, addr := range addrs { peers[i] = &pex.Peer{Addr: addr} } m := NewGivePeersMessage(peers) assert.Equal(t, len(m.GetPeers()), 2) testSimpleMessageHandler(t, d, m) assert.Equal(t, m.GetPeers()[0], addrs[0]) assert.Equal(t, m.GetPeers()[1], addrs[1]) // Test disabled d.Peers.Config.Disabled = true m.Process(d) assert.Equal(t, len(d.Peers.Peers.Peerlist), 0) // Test serialization m = NewGivePeersMessage(peers) b := encoder.Serialize(m) m2 := GivePeersMessage{} assert.Nil(t, encoder.DeserializeRaw(b, &m2)) assert.Equal(t, *m, m2) // Peers should be added to the pex when processed d.Peers.Config.Disabled = false m.Process(d) assert.Equal(t, len(d.Peers.Peers.Peerlist), 2) gnet.EraseMessages() }
func TestGetPeersMessage(t *testing.T) { d := newDefaultDaemon() defer shutdown(d) p := d.Pool m := NewGetPeersMessage() testSimpleMessageHandler(t, d, m) d.Peers.Peers.AddPeer(addr) q, err := d.Peers.Peers.AddPeer(addrb) assert.Nil(t, err) q.Private = true d.Peers.Config.ReplyCount = 100 m.c = messageContext(addr) // Peers disabled d.Peers.Config.Disabled = true assert.NotPanics(t, func() { m.Process(d) }) wait() assert.Equal(t, len(p.Pool.SendResults), 0) assert.True(t, m.c.Conn.LastSent.IsZero()) // Peers enabled d.Peers.Config.Disabled = false m.c = messageContext(addr) defer m.c.Conn.Close() go p.Pool.ConnectionWriteLoop(m.c.Conn) assert.NotPanics(t, func() { m.Process(d) }) wait() assert.Equal(t, len(p.Pool.SendResults), 1) if len(p.Pool.SendResults) == 0 { t.Fatal("SendResults empty, would block") } sr := <-p.Pool.SendResults assert.Nil(t, sr.Error) assert.Equal(t, sr.Connection, m.c.Conn) msg, ok := sr.Message.(*GivePeersMessage) assert.True(t, ok) // Private peer should not be included ipAddr, err := NewIPAddr(addr) assert.Nil(t, err) assert.Equal(t, msg.Peers, []IPAddr{ipAddr}) assert.False(t, m.c.Conn.LastSent.IsZero()) // If no peers, nothing should happen m.c.Conn.LastSent = util.ZeroTime() delete(d.Peers.Peers.Peerlist, addr) assert.NotPanics(t, func() { m.Process(d) }) wait() assert.Equal(t, len(p.Pool.SendResults), 0) assert.True(t, m.c.Conn.LastSent.IsZero()) // Test serialization m = NewGetPeersMessage() b := encoder.Serialize(m) m2 := GetPeersMessage{} assert.Nil(t, encoder.DeserializeRaw(b, &m2)) assert.Equal(t, *m, m2) gnet.EraseMessages() }
func TestIntroductionMessageProcess(t *testing.T) { cleanupPeers() d := newDefaultDaemon() defer shutdown(d) m := NewIntroductionMessage(d.Messages.Mirror, d.Config.Version, uint16(poolPort)) m.c = messageContext(addr) d.Pool.Pool.Pool[1] = m.c.Conn // Test invalid m.valid = false d.ExpectingIntroductions[addr] = time.Now() m.Process(d) // d.ExpectingIntroductions should get updated _, x := d.ExpectingIntroductions[addr] assert.False(t, x) // d.mirrorConnections should not have an entry _, x = d.mirrorConnections[m.Mirror] assert.False(t, x) assert.Equal(t, len(d.Peers.Peers.Peerlist), 0) // Test valid m.valid = true d.ExpectingIntroductions[addr] = time.Now() m.Process(d) // d.ExpectingIntroductions should get updated _, x = d.ExpectingIntroductions[addr] assert.False(t, x) assert.Equal(t, len(d.Peers.Peers.Peerlist), 1) assert.Equal(t, d.ConnectionMirrors[addr], m.Mirror) assert.NotNil(t, d.mirrorConnections[m.Mirror]) assert.Equal(t, d.mirrorConnections[m.Mirror][addrIP], addrPort) peerAddr := fmt.Sprintf("%s:%d", addrIP, poolPort) assert.NotNil(t, d.Peers.Peers.Peerlist[peerAddr]) // Handle impossibly bad ip:port returned from conn.Addr() // User should be disconnected m.valid = true m.c = messageContext(badAddrPort) m.Process(d) if len(d.Pool.Pool.DisconnectQueue) != 1 { t.Fatalf("DisconnectQueue empty") } <-d.Pool.Pool.DisconnectQueue m.valid = true m.c = messageContext(badAddrNoPort) m.Process(d) if len(d.Pool.Pool.DisconnectQueue) != 1 { t.Fatalf("DisconnectQueue empty") } <-d.Pool.Pool.DisconnectQueue gnet.EraseMessages() }
func TestIntroductionMessageHandle(t *testing.T) { d := newDefaultDaemon() defer shutdown(d) mc := messageContext(addr) m := NewIntroductionMessage(d.Messages.Mirror, d.Config.Version, d.Pool.Pool.Config.Port) // Test valid handling m.Mirror = d.Messages.Mirror + 1 err := m.Handle(mc, d) assert.Nil(t, err) if len(d.messageEvents) == 0 { t.Fatalf("messageEvent is empty") } <-d.messageEvents assert.True(t, m.valid) m.valid = false // Test matching mirror m.Mirror = d.Messages.Mirror err = m.Handle(mc, d) assert.Equal(t, err, DisconnectSelf) m.Mirror = d.Messages.Mirror + 1 assert.False(t, m.valid) // Test mismatched d.Config.Version m.Version = d.Config.Version + 1 err = m.Handle(mc, d) assert.Equal(t, err, DisconnectInvalidVersion) assert.False(t, m.valid) // Test serialization m = NewIntroductionMessage(d.Messages.Mirror, d.Config.Version, d.Pool.Pool.Config.Port) b := encoder.Serialize(m) m2 := IntroductionMessage{} assert.Nil(t, encoder.DeserializeRaw(b, &m2)) assert.Equal(t, *m, m2) // Test already connected d.mirrorConnections[m.Mirror] = make(map[string]uint16) d.mirrorConnections[m.Mirror][addrIP] = addrPort + 1 err = m.Handle(mc, d) assert.Equal(t, err, DisconnectConnectedTwice) delete(d.mirrorConnections, m.Mirror) assert.False(t, m.valid) for len(d.messageEvents) > 0 { <-d.messageEvents } gnet.EraseMessages() }
func TestRequestPeers(t *testing.T) { defer cleanupPeers() gnet.EraseMessages() defer gnet.EraseMessages() // Disabled c := NewPeersConfig() c.Disabled = true p := NewPeers(c) assert.NotPanics(t, func() { p.requestPeers(nil) }) // Full c.Disabled = false c.Max = 1 p = NewPeers(c) p.Init() p.Peers.AddPeer(addr) assert.NotPanics(t, func() { p.requestPeers(nil) }) // Not full, will send message c.Max = 10 p = NewPeers(c) p.Init() p.Peers.AddPeer(addr) pool, gc := setupPool() go pool.Pool.ConnectionWriteLoop(gc) defer gc.Close() assert.NotPanics(t, func() { p.requestPeers(pool) }) wait() assert.Equal(t, len(pool.Pool.SendResults), 1) if len(pool.Pool.SendResults) == 0 { t.Fatalf("SendResults empty, would block") } sr := <-pool.Pool.SendResults assert.Equal(t, sr.Connection, gc) assert.Nil(t, sr.Error) _, ok := sr.Message.(*GetPeersMessage) assert.True(t, ok) }
func TestPongMessage(t *testing.T) { cmsgs := NewMessagesConfig() cmsgs.Register() m := &PongMessage{} // Pongs dont do anything assert.Nil(t, m.Handle(messageContext(addr), nil)) gnet.EraseMessages() // Test serialization mm := PongMessage{} b := encoder.Serialize(mm) m2 := PongMessage{} assert.Nil(t, encoder.DeserializeRaw(b, &m2)) assert.Equal(t, mm, m2) }
func TestStart(t *testing.T) { gnet.EraseMessages() defer cleanupPeers() d, quit := setupDaemonLoopDHT() defer closeDaemon(d, quit) assert.NotNil(t, d) assert.NotNil(t, d.Pool) assert.NotNil(t, d.DHT) go d.Start(quit) wait() assert.NotEqual(t, len(gnet.MessageIdMap), 0) assert.NotNil(t, d.Pool) assert.NotNil(t, d.Peers) assert.NotNil(t, d.DHT) assert.NotNil(t, d.Messages) assert.NotNil(t, d.Gateway) }
func TestRegisterMessages(t *testing.T) { gnet.EraseMessages() c := NewMessagesConfig() assert.NotPanics(t, c.Register) gnet.EraseMessages() }
// Terminates all subsystems safely. To stop the Daemon run loop, send a value // over the quit channel provided to Init. The Daemon run loop must be stopped // before calling this function. func (self *Daemon) Shutdown() { self.Pool.Shutdown() self.Peers.Shutdown() self.Visor.Shutdown() gnet.EraseMessages() }
func TestOnConnect(t *testing.T) { d := newDefaultDaemon() // Test a valid connection, unsolicited e := ConnectEvent{addr, false} p, _ := d.Peers.Peers.AddPeer(addr) c := setupExistingPool(d.Pool) go d.Pool.Pool.ConnectionWriteLoop(c) d.pendingConnections[addr] = p assert.NotPanics(t, func() { d.onConnect(e) }) wait() assert.Equal(t, len(d.Pool.Pool.SendResults), 1) if len(d.Pool.Pool.SendResults) == 0 { t.Fatalf("SendResults empty, would block") } sr := <-d.Pool.Pool.SendResults assert.Equal(t, sr.Connection, c) assert.Nil(t, sr.Error) _, ok := sr.Message.(*IntroductionMessage) assert.True(t, ok) // This connection should no longer be pending assert.Equal(t, len(d.pendingConnections), 0) // This is not an outgoing connection, we did not solicit it assert.Equal(t, len(d.OutgoingConnections), 0) // We should be expecting its version assert.Equal(t, len(d.ExpectingIntroductions), 1) _, exists := d.ExpectingIntroductions[addr] assert.True(t, exists) // An introduction should have been sent assert.False(t, c.LastSent.IsZero()) // d.ipCounts should be 1 assert.Equal(t, d.ipCounts[addrIP], 1) // Cleanup delete(d.ipCounts, addrIP) delete(d.ExpectingIntroductions, addr) c.Close() // Test a valid connection, solicited e = ConnectEvent{addr, true} c = gnetConnection(addr) go d.Pool.Pool.ConnectionWriteLoop(c) d.pendingConnections[addr] = p d.Pool.Pool.Addresses[addr] = c d.Pool.Pool.Pool[c.Id] = c assert.NotPanics(t, func() { d.onConnect(e) }) wait() assert.Equal(t, len(d.Pool.Pool.SendResults), 1) if len(d.Pool.Pool.SendResults) == 0 { t.Fatalf("SendResults empty, would block") } sr = <-d.Pool.Pool.SendResults assert.Equal(t, sr.Connection, c) assert.Nil(t, sr.Error) _, ok = sr.Message.(*IntroductionMessage) assert.True(t, ok) // This connection should no longer be pending assert.Equal(t, len(d.pendingConnections), 0) // We should mark this as an outgoing connection since we solicited it assert.Equal(t, len(d.OutgoingConnections), 1) assert.NotNil(t, d.OutgoingConnections[addr]) // We should be expecting its version assert.Equal(t, len(d.ExpectingIntroductions), 1) _, exists = d.ExpectingIntroductions[addr] assert.True(t, exists) // An introduction should have been sent assert.False(t, c.LastSent.IsZero()) // d.ipCounts should be 1 assert.Equal(t, d.ipCounts[addrIP], 1) // Cleanup c.Close() delete(d.ExpectingIntroductions, addr) delete(d.OutgoingConnections, addr) delete(d.ipCounts, addrIP) // Test a connection that is not connected by the time of processing c.LastSent = util.ZeroTime() e = ConnectEvent{addr, true} delete(d.Pool.Pool.Addresses, addr) d.pendingConnections[addr] = p assert.NotPanics(t, func() { d.onConnect(e) }) wait() assert.Equal(t, len(d.Pool.Pool.SendResults), 0) // This connection should no longer be pending assert.Equal(t, len(d.pendingConnections), 0) // No message should have been sent assert.True(t, c.LastSent.IsZero()) // We should not be expecting its version assert.Equal(t, len(d.ExpectingIntroductions), 0) // We should not have recorded it to ipCount assert.Equal(t, d.ipCounts[addrIP], 0) // Test a connection that is blacklisted e = ConnectEvent{addr, true} c = gnetConnection(addr) go d.Pool.Pool.ConnectionWriteLoop(c) d.Peers.Peers.AddBlacklistEntry(addr, time.Hour) d.pendingConnections[addr] = p d.Pool.Pool.Addresses[addr] = c d.Pool.Pool.Pool[c.Id] = c assert.NotPanics(t, func() { d.onConnect(e) }) wait() // No introduction should have been sent assert.Equal(t, len(d.Pool.Pool.SendResults), 0) // This connection should no longer be pending assert.Equal(t, len(d.pendingConnections), 0) // No message should have been sent assert.True(t, c.LastSent.IsZero()) // We should not be expecting its version assert.Equal(t, len(d.ExpectingIntroductions), 0) // We should not have recorded its ipCount assert.Equal(t, d.ipCounts[addrIP], 0) // We should be looking to disconnect this client assert.Equal(t, len(d.Pool.Pool.DisconnectQueue), 1) if len(d.Pool.Pool.DisconnectQueue) == 0 { t.Fatal("pool.Pool.DisconnectQueue is empty, would block") } de := <-d.Pool.Pool.DisconnectQueue assert.Equal(t, de.ConnId, 1) assert.Equal(t, de.Reason, DisconnectIsBlacklisted) // Cleanup c.Close() delete(d.Peers.Peers.Blacklist, addr) // Test a connection that has reached maxed ipCount e = ConnectEvent{addr, true} c = gnetConnection(addr) go d.Pool.Pool.ConnectionWriteLoop(c) d.ipCounts[addrIP] = d.Config.IPCountsMax d.pendingConnections[addr] = p d.Pool.Pool.Addresses[addr] = c d.Pool.Pool.Pool[c.Id] = c assert.NotPanics(t, func() { d.onConnect(e) }) wait() // No introduction should have been sent assert.Equal(t, len(d.Pool.Pool.SendResults), 0) // This connection should no longer be pending assert.Equal(t, len(d.pendingConnections), 0) // No message should have been sent assert.True(t, c.LastSent.IsZero()) // We should not be expecting its version assert.Equal(t, len(d.ExpectingIntroductions), 0) // d.ipCounts should be unchanged assert.Equal(t, d.ipCounts[addrIP], d.Config.IPCountsMax) // We should be looking to disconnect this client assert.Equal(t, len(d.Pool.Pool.DisconnectQueue), 1) if len(d.Pool.Pool.DisconnectQueue) == 0 { t.Fatal("pool.Pool.DisconnectQueue is empty, would block") } de = <-d.Pool.Pool.DisconnectQueue assert.Equal(t, de.ConnId, 1) assert.Equal(t, de.Reason, DisconnectIPLimitReached) // Cleanup c.Close() delete(d.ipCounts, addrIP) gnet.EraseMessages() shutdown(d) }
func shutdown(d *Daemon) { d.Shutdown() wait() cleanupPeers() gnet.EraseMessages() }