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.

391 lines
9.5 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
8 years ago
8 years ago
8 years ago
  1. package pex
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "testing"
  8. "github.com/stretchr/testify/assert"
  9. cmn "github.com/tendermint/tendermint/libs/common"
  10. "github.com/tendermint/tendermint/libs/log"
  11. "github.com/tendermint/tendermint/p2p"
  12. )
  13. func createTempFileName(prefix string) string {
  14. f, err := ioutil.TempFile("", prefix)
  15. if err != nil {
  16. panic(err)
  17. }
  18. fname := f.Name()
  19. err = f.Close()
  20. if err != nil {
  21. panic(err)
  22. }
  23. return fname
  24. }
  25. func deleteTempFile(fname string) {
  26. err := os.Remove(fname)
  27. if err != nil {
  28. panic(err)
  29. }
  30. }
  31. func TestAddrBookPickAddress(t *testing.T) {
  32. fname := createTempFileName("addrbook_test")
  33. defer deleteTempFile(fname)
  34. // 0 addresses
  35. book := NewAddrBook(fname, true)
  36. book.SetLogger(log.TestingLogger())
  37. assert.Zero(t, book.Size())
  38. addr := book.PickAddress(50)
  39. assert.Nil(t, addr, "expected no address")
  40. randAddrs := randNetAddressPairs(t, 1)
  41. addrSrc := randAddrs[0]
  42. book.AddAddress(addrSrc.addr, addrSrc.src)
  43. // pick an address when we only have new address
  44. addr = book.PickAddress(0)
  45. assert.NotNil(t, addr, "expected an address")
  46. addr = book.PickAddress(50)
  47. assert.NotNil(t, addr, "expected an address")
  48. addr = book.PickAddress(100)
  49. assert.NotNil(t, addr, "expected an address")
  50. // pick an address when we only have old address
  51. book.MarkGood(addrSrc.addr)
  52. addr = book.PickAddress(0)
  53. assert.NotNil(t, addr, "expected an address")
  54. addr = book.PickAddress(50)
  55. assert.NotNil(t, addr, "expected an address")
  56. // in this case, nNew==0 but we biased 100% to new, so we return nil
  57. addr = book.PickAddress(100)
  58. assert.Nil(t, addr, "did not expected an address")
  59. }
  60. func TestAddrBookSaveLoad(t *testing.T) {
  61. fname := createTempFileName("addrbook_test")
  62. defer deleteTempFile(fname)
  63. // 0 addresses
  64. book := NewAddrBook(fname, true)
  65. book.SetLogger(log.TestingLogger())
  66. book.saveToFile(fname)
  67. book = NewAddrBook(fname, true)
  68. book.SetLogger(log.TestingLogger())
  69. book.loadFromFile(fname)
  70. assert.Zero(t, book.Size())
  71. // 100 addresses
  72. randAddrs := randNetAddressPairs(t, 100)
  73. for _, addrSrc := range randAddrs {
  74. book.AddAddress(addrSrc.addr, addrSrc.src)
  75. }
  76. assert.Equal(t, 100, book.Size())
  77. book.saveToFile(fname)
  78. book = NewAddrBook(fname, true)
  79. book.SetLogger(log.TestingLogger())
  80. book.loadFromFile(fname)
  81. assert.Equal(t, 100, book.Size())
  82. }
  83. func TestAddrBookLookup(t *testing.T) {
  84. fname := createTempFileName("addrbook_test")
  85. defer deleteTempFile(fname)
  86. randAddrs := randNetAddressPairs(t, 100)
  87. book := NewAddrBook(fname, true)
  88. book.SetLogger(log.TestingLogger())
  89. for _, addrSrc := range randAddrs {
  90. addr := addrSrc.addr
  91. src := addrSrc.src
  92. book.AddAddress(addr, src)
  93. ka := book.addrLookup[addr.ID]
  94. assert.NotNil(t, ka, "Expected to find KnownAddress %v but wasn't there.", addr)
  95. if !(ka.Addr.Equals(addr) && ka.Src.Equals(src)) {
  96. t.Fatalf("KnownAddress doesn't match addr & src")
  97. }
  98. }
  99. }
  100. func TestAddrBookPromoteToOld(t *testing.T) {
  101. fname := createTempFileName("addrbook_test")
  102. defer deleteTempFile(fname)
  103. randAddrs := randNetAddressPairs(t, 100)
  104. book := NewAddrBook(fname, true)
  105. book.SetLogger(log.TestingLogger())
  106. for _, addrSrc := range randAddrs {
  107. book.AddAddress(addrSrc.addr, addrSrc.src)
  108. }
  109. // Attempt all addresses.
  110. for _, addrSrc := range randAddrs {
  111. book.MarkAttempt(addrSrc.addr)
  112. }
  113. // Promote half of them
  114. for i, addrSrc := range randAddrs {
  115. if i%2 == 0 {
  116. book.MarkGood(addrSrc.addr)
  117. }
  118. }
  119. // TODO: do more testing :)
  120. selection := book.GetSelection()
  121. t.Logf("selection: %v", selection)
  122. if len(selection) > book.Size() {
  123. t.Errorf("selection could not be bigger than the book")
  124. }
  125. selection = book.GetSelectionWithBias(30)
  126. t.Logf("selection: %v", selection)
  127. if len(selection) > book.Size() {
  128. t.Errorf("selection with bias could not be bigger than the book")
  129. }
  130. assert.Equal(t, book.Size(), 100, "expecting book size to be 100")
  131. }
  132. func TestAddrBookHandlesDuplicates(t *testing.T) {
  133. fname := createTempFileName("addrbook_test")
  134. defer deleteTempFile(fname)
  135. book := NewAddrBook(fname, true)
  136. book.SetLogger(log.TestingLogger())
  137. randAddrs := randNetAddressPairs(t, 100)
  138. differentSrc := randIPv4Address(t)
  139. for _, addrSrc := range randAddrs {
  140. book.AddAddress(addrSrc.addr, addrSrc.src)
  141. book.AddAddress(addrSrc.addr, addrSrc.src) // duplicate
  142. book.AddAddress(addrSrc.addr, differentSrc) // different src
  143. }
  144. assert.Equal(t, 100, book.Size())
  145. }
  146. type netAddressPair struct {
  147. addr *p2p.NetAddress
  148. src *p2p.NetAddress
  149. }
  150. func randNetAddressPairs(t *testing.T, n int) []netAddressPair {
  151. randAddrs := make([]netAddressPair, n)
  152. for i := 0; i < n; i++ {
  153. randAddrs[i] = netAddressPair{addr: randIPv4Address(t), src: randIPv4Address(t)}
  154. }
  155. return randAddrs
  156. }
  157. func randIPv4Address(t *testing.T) *p2p.NetAddress {
  158. for {
  159. ip := fmt.Sprintf("%v.%v.%v.%v",
  160. cmn.RandIntn(254)+1,
  161. cmn.RandIntn(255),
  162. cmn.RandIntn(255),
  163. cmn.RandIntn(255),
  164. )
  165. port := cmn.RandIntn(65535-1) + 1
  166. id := p2p.ID(hex.EncodeToString(cmn.RandBytes(p2p.IDByteLength)))
  167. idAddr := p2p.IDAddressString(id, fmt.Sprintf("%v:%v", ip, port))
  168. addr, err := p2p.NewNetAddressString(idAddr)
  169. assert.Nil(t, err, "error generating rand network address")
  170. if addr.Routable() {
  171. return addr
  172. }
  173. }
  174. }
  175. func TestAddrBookRemoveAddress(t *testing.T) {
  176. fname := createTempFileName("addrbook_test")
  177. defer deleteTempFile(fname)
  178. book := NewAddrBook(fname, true)
  179. book.SetLogger(log.TestingLogger())
  180. addr := randIPv4Address(t)
  181. book.AddAddress(addr, addr)
  182. assert.Equal(t, 1, book.Size())
  183. book.RemoveAddress(addr)
  184. assert.Equal(t, 0, book.Size())
  185. nonExistingAddr := randIPv4Address(t)
  186. book.RemoveAddress(nonExistingAddr)
  187. assert.Equal(t, 0, book.Size())
  188. }
  189. func TestAddrBookGetSelection(t *testing.T) {
  190. fname := createTempFileName("addrbook_test")
  191. defer deleteTempFile(fname)
  192. book := NewAddrBook(fname, true)
  193. book.SetLogger(log.TestingLogger())
  194. // 1) empty book
  195. assert.Empty(t, book.GetSelection())
  196. // 2) add one address
  197. addr := randIPv4Address(t)
  198. book.AddAddress(addr, addr)
  199. assert.Equal(t, 1, len(book.GetSelection()))
  200. assert.Equal(t, addr, book.GetSelection()[0])
  201. // 3) add a bunch of addresses
  202. randAddrs := randNetAddressPairs(t, 100)
  203. for _, addrSrc := range randAddrs {
  204. book.AddAddress(addrSrc.addr, addrSrc.src)
  205. }
  206. // check there is no duplicates
  207. addrs := make(map[string]*p2p.NetAddress)
  208. selection := book.GetSelection()
  209. for _, addr := range selection {
  210. if dup, ok := addrs[addr.String()]; ok {
  211. t.Fatalf("selection %v contains duplicates %v", selection, dup)
  212. }
  213. addrs[addr.String()] = addr
  214. }
  215. if len(selection) > book.Size() {
  216. t.Errorf("selection %v could not be bigger than the book", selection)
  217. }
  218. }
  219. func TestAddrBookGetSelectionWithBias(t *testing.T) {
  220. const biasTowardsNewAddrs = 30
  221. fname := createTempFileName("addrbook_test")
  222. defer deleteTempFile(fname)
  223. book := NewAddrBook(fname, true)
  224. book.SetLogger(log.TestingLogger())
  225. // 1) empty book
  226. selection := book.GetSelectionWithBias(biasTowardsNewAddrs)
  227. assert.Empty(t, selection)
  228. // 2) add one address
  229. addr := randIPv4Address(t)
  230. book.AddAddress(addr, addr)
  231. selection = book.GetSelectionWithBias(biasTowardsNewAddrs)
  232. assert.Equal(t, 1, len(selection))
  233. assert.Equal(t, addr, selection[0])
  234. // 3) add a bunch of addresses
  235. randAddrs := randNetAddressPairs(t, 100)
  236. for _, addrSrc := range randAddrs {
  237. book.AddAddress(addrSrc.addr, addrSrc.src)
  238. }
  239. // check there is no duplicates
  240. addrs := make(map[string]*p2p.NetAddress)
  241. selection = book.GetSelectionWithBias(biasTowardsNewAddrs)
  242. for _, addr := range selection {
  243. if dup, ok := addrs[addr.String()]; ok {
  244. t.Fatalf("selection %v contains duplicates %v", selection, dup)
  245. }
  246. addrs[addr.String()] = addr
  247. }
  248. if len(selection) > book.Size() {
  249. t.Fatalf("selection %v could not be bigger than the book", selection)
  250. }
  251. // 4) mark 80% of the addresses as good
  252. randAddrsLen := len(randAddrs)
  253. for i, addrSrc := range randAddrs {
  254. if int((float64(i)/float64(randAddrsLen))*100) >= 20 {
  255. book.MarkGood(addrSrc.addr)
  256. }
  257. }
  258. selection = book.GetSelectionWithBias(biasTowardsNewAddrs)
  259. // check that ~70% of addresses returned are good
  260. good := 0
  261. for _, addr := range selection {
  262. if book.IsGood(addr) {
  263. good++
  264. }
  265. }
  266. got, expected := int((float64(good)/float64(len(selection)))*100), (100 - biasTowardsNewAddrs)
  267. if got >= expected {
  268. t.Fatalf("expected more good peers (%% got: %d, %% expected: %d, number of good addrs: %d, total: %d)", got, expected, good, len(selection))
  269. }
  270. }
  271. func TestAddrBookHasAddress(t *testing.T) {
  272. fname := createTempFileName("addrbook_test")
  273. defer deleteTempFile(fname)
  274. book := NewAddrBook(fname, true)
  275. book.SetLogger(log.TestingLogger())
  276. addr := randIPv4Address(t)
  277. book.AddAddress(addr, addr)
  278. assert.True(t, book.HasAddress(addr))
  279. book.RemoveAddress(addr)
  280. assert.False(t, book.HasAddress(addr))
  281. }
  282. func TestPrivatePeers(t *testing.T) {
  283. fname := createTempFileName("addrbook_test")
  284. defer deleteTempFile(fname)
  285. book := NewAddrBook(fname, true)
  286. book.SetLogger(log.TestingLogger())
  287. addrs := make([]*p2p.NetAddress, 10)
  288. for i := 0; i < 10; i++ {
  289. addrs[i] = randIPv4Address(t)
  290. }
  291. private := make([]string, 10)
  292. for i, addr := range addrs {
  293. private[i] = string(addr.ID)
  294. }
  295. book.AddPrivateIDs(private)
  296. // private addrs must not be added
  297. for _, addr := range addrs {
  298. err := book.AddAddress(addr, addr)
  299. if assert.Error(t, err) {
  300. _, ok := err.(ErrAddrBookPrivate)
  301. assert.True(t, ok)
  302. }
  303. }
  304. // addrs coming from private peers must not be added
  305. err := book.AddAddress(randIPv4Address(t), addrs[0])
  306. if assert.Error(t, err) {
  307. _, ok := err.(ErrAddrBookPrivateSrc)
  308. assert.True(t, ok)
  309. }
  310. }