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.

256 lines
7.9 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(t, nodeKeyID, name)
  64. ni.Channels = channels
  65. assert.NoError(t, ni.Validate())
  66. for _, tc := range testCases {
  67. t.Run(tc.testName, func(t *testing.T) {
  68. ni := testNodeInfo(t, nodeKeyID, name)
  69. ni.Channels = channels
  70. tc.malleateNodeInfo(&ni)
  71. err := ni.Validate()
  72. if tc.expectErr {
  73. assert.Error(t, err, tc.testName)
  74. } else {
  75. assert.NoError(t, err, tc.testName)
  76. }
  77. })
  78. }
  79. }
  80. func testNodeID() NodeID {
  81. return NodeIDFromPubKey(ed25519.GenPrivKey().PubKey())
  82. }
  83. func testNodeInfo(t *testing.T, id NodeID, name string) NodeInfo {
  84. return testNodeInfoWithNetwork(t, id, name, "testing")
  85. }
  86. func testNodeInfoWithNetwork(t *testing.T, id NodeID, name, network string) NodeInfo {
  87. t.Helper()
  88. return NodeInfo{
  89. ProtocolVersion: ProtocolVersion{
  90. P2P: version.P2PProtocol,
  91. Block: version.BlockProtocol,
  92. App: 0,
  93. },
  94. NodeID: id,
  95. ListenAddr: fmt.Sprintf("127.0.0.1:%d", getFreePort(t)),
  96. Network: network,
  97. Version: "1.2.3-rc0-deadbeef",
  98. Channels: []byte{testCh},
  99. Moniker: name,
  100. Other: NodeInfoOther{
  101. TxIndex: "on",
  102. RPCAddress: fmt.Sprintf("127.0.0.1:%d", getFreePort(t)),
  103. },
  104. }
  105. }
  106. func getFreePort(t *testing.T) int {
  107. t.Helper()
  108. port, err := tmnet.GetFreePort()
  109. require.NoError(t, err)
  110. return port
  111. }
  112. func TestNodeInfoCompatible(t *testing.T) {
  113. nodeKey1ID := testNodeID()
  114. nodeKey2ID := testNodeID()
  115. name := "testing"
  116. var newTestChannel byte = 0x2
  117. // test NodeInfo is compatible
  118. ni1 := testNodeInfo(t, nodeKey1ID, name)
  119. ni2 := testNodeInfo(t, nodeKey2ID, name)
  120. assert.NoError(t, ni1.CompatibleWith(ni2))
  121. // add another channel; still compatible
  122. ni2.Channels = []byte{newTestChannel, testCh}
  123. assert.NoError(t, ni1.CompatibleWith(ni2))
  124. testCases := []struct {
  125. testName string
  126. malleateNodeInfo func(*NodeInfo)
  127. }{
  128. {"Wrong block version", func(ni *NodeInfo) { ni.ProtocolVersion.Block++ }},
  129. {"Wrong network", func(ni *NodeInfo) { ni.Network += "-wrong" }},
  130. {"No common channels", func(ni *NodeInfo) { ni.Channels = []byte{newTestChannel} }},
  131. }
  132. for _, tc := range testCases {
  133. ni := testNodeInfo(t, nodeKey2ID, name)
  134. tc.malleateNodeInfo(&ni)
  135. assert.Error(t, ni1.CompatibleWith(ni))
  136. }
  137. }
  138. func TestNodeInfoAddChannel(t *testing.T) {
  139. nodeInfo := testNodeInfo(t, testNodeID(), "testing")
  140. nodeInfo.Channels = []byte{}
  141. require.Empty(t, nodeInfo.Channels)
  142. nodeInfo.AddChannel(2)
  143. require.Contains(t, nodeInfo.Channels, byte(0x02))
  144. // adding the same channel again shouldn't be a problem
  145. nodeInfo.AddChannel(2)
  146. require.Contains(t, nodeInfo.Channels, byte(0x02))
  147. }
  148. func TestParseAddressString(t *testing.T) {
  149. testCases := []struct {
  150. name string
  151. addr string
  152. expected string
  153. correct bool
  154. }{
  155. {"no node id and no protocol", "127.0.0.1:8080", "", false},
  156. {"no node id w/ tcp input", "tcp://127.0.0.1:8080", "", false},
  157. {"no node id w/ udp input", "udp://127.0.0.1:8080", "", false},
  158. {
  159. "no protocol",
  160. "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  161. "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  162. true,
  163. },
  164. {
  165. "tcp input",
  166. "tcp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  167. "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  168. true,
  169. },
  170. {
  171. "udp input",
  172. "udp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  173. "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  174. true,
  175. },
  176. {"malformed tcp input", "tcp//deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
  177. {"malformed udp input", "udp//deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
  178. // {"127.0.0:8080", false},
  179. {"invalid host", "notahost", "", false},
  180. {"invalid port", "127.0.0.1:notapath", "", false},
  181. {"invalid host w/ port", "notahost:8080", "", false},
  182. {"just a port", "8082", "", false},
  183. {"non-existent port", "127.0.0:8080000", "", false},
  184. {"too short nodeId", "deadbeef@127.0.0.1:8080", "", false},
  185. {"too short, not hex nodeId", "this-isnot-hex@127.0.0.1:8080", "", false},
  186. {"not hex nodeId", "xxxxbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
  187. {"too short nodeId w/tcp", "tcp://deadbeef@127.0.0.1:8080", "", false},
  188. {"too short notHex nodeId w/tcp", "tcp://this-isnot-hex@127.0.0.1:8080", "", false},
  189. {"notHex nodeId w/tcp", "tcp://xxxxbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false},
  190. {
  191. "correct nodeId w/tcp",
  192. "tcp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  193. "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080",
  194. true,
  195. },
  196. {"no node id", "tcp://@127.0.0.1:8080", "", false},
  197. {"no node id or IP", "tcp://@", "", false},
  198. {"tcp no host, w/ port", "tcp://:26656", "", false},
  199. {"empty", "", "", false},
  200. {"node id delimiter 1", "@", "", false},
  201. {"node id delimiter 2", " @", "", false},
  202. {"node id delimiter 3", " @ ", "", false},
  203. }
  204. for _, tc := range testCases {
  205. tc := tc
  206. t.Run(tc.name, func(t *testing.T) {
  207. addr, port, err := ParseAddressString(tc.addr)
  208. if tc.correct {
  209. require.NoError(t, err, tc.addr)
  210. assert.Contains(t, tc.expected, addr.String())
  211. assert.Contains(t, tc.expected, fmt.Sprint(port))
  212. } else {
  213. assert.Error(t, err, "%v", tc.addr)
  214. }
  215. })
  216. }
  217. }