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.

340 lines
8.3 KiB

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