You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
7.8 KiB

  1. package types
  2. import (
  3. "fmt"
  4. "testing"
  5. "github.com/stretchr/testify/assert"
  6. "github.com/stretchr/testify/require"
  7. "github.com/tendermint/tendermint/crypto/ed25519"
  8. tmnet "github.com/tendermint/tendermint/libs/net"
  9. "github.com/tendermint/tendermint/version"
  10. )
  11. const testCh = 0x01
  12. func TestNodeInfoValidate(t *testing.T) {
  13. // empty fails
  14. ni := NodeInfo{}
  15. assert.Error(t, ni.Validate())
  16. channels := make([]byte, maxNumChannels)
  17. for i := 0; i < maxNumChannels; i++ {
  18. channels[i] = byte(i)
  19. }
  20. dupChannels := make([]byte, 5)
  21. copy(dupChannels, channels[:5])
  22. dupChannels = append(dupChannels, testCh)
  23. nonASCII := "¢§µ"
  24. emptyTab := "\t"
  25. emptySpace := " "
  26. testCases := []struct {
  27. testName string
  28. malleateNodeInfo func(*NodeInfo)
  29. expectErr bool
  30. }{
  31. {
  32. "Too Many Channels",
  33. func(ni *NodeInfo) { ni.Channels = append(channels, byte(maxNumChannels)) }, // nolint: gocritic
  34. true,
  35. },
  36. {"Duplicate Channel", func(ni *NodeInfo) { ni.Channels = dupChannels }, true},
  37. {"Good Channels", func(ni *NodeInfo) { ni.Channels = ni.Channels[:5] }, false},
  38. {"Invalid NetAddress", func(ni *NodeInfo) { ni.ListenAddr = "not-an-address" }, true},
  39. {"Good NetAddress", func(ni *NodeInfo) { ni.ListenAddr = "0.0.0.0:26656" }, false},
  40. {"Non-ASCII Version", func(ni *NodeInfo) { ni.Version = nonASCII }, true},
  41. {"Empty tab Version", func(ni *NodeInfo) { ni.Version = emptyTab }, true},
  42. {"Empty space Version", func(ni *NodeInfo) { ni.Version = emptySpace }, true},
  43. {"Empty Version", func(ni *NodeInfo) { ni.Version = "" }, false},
  44. {"Non-ASCII Moniker", func(ni *NodeInfo) { ni.Moniker = nonASCII }, true},
  45. {"Empty tab Moniker", func(ni *NodeInfo) { ni.Moniker = emptyTab }, true},
  46. {"Empty space Moniker", func(ni *NodeInfo) { ni.Moniker = emptySpace }, true},
  47. {"Empty Moniker", func(ni *NodeInfo) { ni.Moniker = "" }, true},
  48. {"Good Moniker", func(ni *NodeInfo) { ni.Moniker = "hey its me" }, false},
  49. {"Non-ASCII TxIndex", func(ni *NodeInfo) { ni.Other.TxIndex = nonASCII }, true},
  50. {"Empty tab TxIndex", func(ni *NodeInfo) { ni.Other.TxIndex = emptyTab }, true},
  51. {"Empty space TxIndex", func(ni *NodeInfo) { ni.Other.TxIndex = emptySpace }, true},
  52. {"Empty TxIndex", func(ni *NodeInfo) { ni.Other.TxIndex = "" }, false},
  53. {"Off TxIndex", func(ni *NodeInfo) { ni.Other.TxIndex = "off" }, false},
  54. {"Non-ASCII RPCAddress", func(ni *NodeInfo) { ni.Other.RPCAddress = nonASCII }, true},
  55. {"Empty tab RPCAddress", func(ni *NodeInfo) { ni.Other.RPCAddress = emptyTab }, true},
  56. {"Empty space RPCAddress", func(ni *NodeInfo) { ni.Other.RPCAddress = emptySpace }, true},
  57. {"Empty RPCAddress", func(ni *NodeInfo) { ni.Other.RPCAddress = "" }, false},
  58. {"Good RPCAddress", func(ni *NodeInfo) { ni.Other.RPCAddress = "0.0.0.0:26657" }, false},
  59. }
  60. nodeKeyID := testNodeID()
  61. name := "testing"
  62. // test case passes
  63. ni = testNodeInfo(nodeKeyID, name)
  64. ni.Channels = channels
  65. assert.NoError(t, ni.Validate())
  66. for _, tc := range testCases {
  67. ni := testNodeInfo(nodeKeyID, name)
  68. ni.Channels = channels
  69. tc.malleateNodeInfo(&ni)
  70. err := ni.Validate()
  71. if tc.expectErr {
  72. assert.Error(t, err, tc.testName)
  73. } else {
  74. assert.NoError(t, err, tc.testName)
  75. }
  76. }
  77. }
  78. func testNodeID() NodeID {
  79. return NodeIDFromPubKey(ed25519.GenPrivKey().PubKey())
  80. }
  81. func testNodeInfo(id NodeID, name string) NodeInfo {
  82. return testNodeInfoWithNetwork(id, name, "testing")
  83. }
  84. func testNodeInfoWithNetwork(id NodeID, name, network string) NodeInfo {
  85. return NodeInfo{
  86. ProtocolVersion: ProtocolVersion{
  87. P2P: version.P2PProtocol,
  88. Block: version.BlockProtocol,
  89. App: 0,
  90. },
  91. NodeID: id,
  92. ListenAddr: fmt.Sprintf("127.0.0.1:%d", getFreePort()),
  93. Network: network,
  94. Version: "1.2.3-rc0-deadbeef",
  95. Channels: []byte{testCh},
  96. Moniker: name,
  97. Other: NodeInfoOther{
  98. TxIndex: "on",
  99. RPCAddress: fmt.Sprintf("127.0.0.1:%d", getFreePort()),
  100. },
  101. }
  102. }
  103. func getFreePort() int {
  104. port, err := tmnet.GetFreePort()
  105. if err != nil {
  106. panic(err)
  107. }
  108. return port
  109. }
  110. func TestNodeInfoCompatible(t *testing.T) {
  111. nodeKey1ID := testNodeID()
  112. nodeKey2ID := testNodeID()
  113. name := "testing"
  114. var newTestChannel byte = 0x2
  115. // test NodeInfo is compatible
  116. ni1 := testNodeInfo(nodeKey1ID, name)
  117. ni2 := testNodeInfo(nodeKey2ID, name)
  118. assert.NoError(t, ni1.CompatibleWith(ni2))
  119. // add another channel; still compatible
  120. ni2.Channels = []byte{newTestChannel, testCh}
  121. assert.NoError(t, ni1.CompatibleWith(ni2))
  122. testCases := []struct {
  123. testName string
  124. malleateNodeInfo func(*NodeInfo)
  125. }{
  126. {"Wrong block version", func(ni *NodeInfo) { ni.ProtocolVersion.Block++ }},
  127. {"Wrong network", func(ni *NodeInfo) { ni.Network += "-wrong" }},
  128. {"No common channels", func(ni *NodeInfo) { ni.Channels = []byte{newTestChannel} }},
  129. }
  130. for _, tc := range testCases {
  131. ni := testNodeInfo(nodeKey2ID, name)
  132. tc.malleateNodeInfo(&ni)
  133. assert.Error(t, ni1.CompatibleWith(ni))
  134. }
  135. }
  136. func TestNodeInfoAddChannel(t *testing.T) {
  137. nodeInfo := testNodeInfo(testNodeID(), "testing")
  138. nodeInfo.Channels = []byte{}
  139. require.Empty(t, nodeInfo.Channels)
  140. nodeInfo.AddChannel(2)
  141. require.Contains(t, nodeInfo.Channels, byte(0x02))
  142. // adding the same channel again shouldn't be a problem
  143. nodeInfo.AddChannel(2)
  144. require.Contains(t, nodeInfo.Channels, byte(0x02))
  145. }
  146. func TestParseAddressString(t *testing.T) {
  147. testCases := []struct {
  148. name string
  149. addr string
  150. expected string
  151. correct bool
  152. }{
  153. {"no node id and no protocol", "127.0.0.1:8080", "", false},
  154. {"no node id w/ tcp input", "tcp://127.0.0.1:8080", "", false},
  155. {"no node id w/ udp input", "udp://127.0.0.1:8080", "", false},
  156. {
  157. "no protocol",
  158. "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  159. "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  160. true,
  161. },
  162. {
  163. "tcp input",
  164. "tcp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  165. "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  166. true,
  167. },
  168. {
  169. "udp input",
  170. "udp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  171. "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  172. true,
  173. },
  174. {"malformed tcp input", "tcp//deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
  175. {"malformed udp input", "udp//deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
  176. // {"127.0.0:8080", false},
  177. {"invalid host", "notahost", "", false},
  178. {"invalid port", "127.0.0.1:notapath", "", false},
  179. {"invalid host w/ port", "notahost:8080", "", false},
  180. {"just a port", "8082", "", false},
  181. {"non-existent port", "127.0.0:8080000", "", false},
  182. {"too short nodeId", "deadbeef@127.0.0.1:8080", "", false},
  183. {"too short, not hex nodeId", "this-isnot-hex@127.0.0.1:8080", "", false},
  184. {"not hex nodeId", "xxxxbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
  185. {"too short nodeId w/tcp", "tcp://deadbeef@127.0.0.1:8080", "", false},
  186. {"too short notHex nodeId w/tcp", "tcp://this-isnot-hex@127.0.0.1:8080", "", false},
  187. {"notHex nodeId w/tcp", "tcp://xxxxbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
  188. {
  189. "correct nodeId w/tcp",
  190. "tcp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  191. "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  192. true,
  193. },
  194. {"no node id", "tcp://@127.0.0.1:8080", "", false},
  195. {"no node id or IP", "tcp://@", "", false},
  196. {"tcp no host, w/ port", "tcp://:26656", "", false},
  197. {"empty", "", "", false},
  198. {"node id delimiter 1", "@", "", false},
  199. {"node id delimiter 2", " @", "", false},
  200. {"node id delimiter 3", " @ ", "", false},
  201. }
  202. for _, tc := range testCases {
  203. tc := tc
  204. t.Run(tc.name, func(t *testing.T) {
  205. addr, port, err := ParseAddressString(tc.addr)
  206. if tc.correct {
  207. require.Nil(t, err, tc.addr)
  208. assert.Contains(t, tc.expected, addr.String())
  209. assert.Contains(t, tc.expected, fmt.Sprint(port))
  210. } else {
  211. assert.Error(t, err, "%v", tc.addr)
  212. }
  213. })
  214. }
  215. }