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.

471 lines
12 KiB

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