vnode_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. package chord_test
  2. import (
  3. "bytes"
  4. "crypto/sha1"
  5. "sort"
  6. "testing"
  7. "time"
  8. "trial/chord"
  9. )
  10. func makeVnode() *chord.LocalVnode {
  11. min := time.Duration(10 * time.Second)
  12. max := time.Duration(30 * time.Second)
  13. conf := &chord.Config{
  14. NumSuccessors: 8,
  15. StabilizeMin: min,
  16. StabilizeMax: max,
  17. HashFunc: sha1.New}
  18. trans := chord.InitLocalTransport(nil)
  19. ring := &chord.Ring{Config: conf, Transport: trans}
  20. return &chord.LocalVnode{Ring: ring}
  21. }
  22. func TestVnodeInit(t *testing.T) {
  23. vn := makeVnode()
  24. vn.Init(0)
  25. if vn.Id == nil {
  26. t.Fatalf("unexpected nil")
  27. }
  28. if vn.Successors == nil {
  29. t.Fatalf("unexpected nil")
  30. }
  31. if vn.Finger == nil {
  32. t.Fatalf("unexpected nil")
  33. }
  34. if vn.Timer != nil {
  35. t.Fatalf("unexpected timer")
  36. }
  37. }
  38. func TestVnodeSchedule(t *testing.T) {
  39. vn := makeVnode()
  40. vn.Schedule()
  41. if vn.Timer == nil {
  42. t.Fatalf("unexpected nil")
  43. }
  44. }
  45. func TestGenId(t *testing.T) {
  46. vn := makeVnode()
  47. var ids [][]byte
  48. for i := 0; i < 16; i++ {
  49. vn.GenId(uint16(i))
  50. ids = append(ids, vn.Id)
  51. }
  52. for idx, val := range ids {
  53. for i := 0; i < len(ids); i++ {
  54. if idx != i && bytes.Compare(ids[i], val) == 0 {
  55. t.Fatalf("unexpected id collision!")
  56. }
  57. }
  58. }
  59. }
  60. func TestVnodeStabilizeShutdown(t *testing.T) {
  61. vn := makeVnode()
  62. vn.Schedule()
  63. vn.Ring.ChanShutdown = make(chan bool, 1)
  64. vn.Stabilize()
  65. if vn.Timer != nil {
  66. t.Fatalf("unexpected timer")
  67. }
  68. if !vn.Stabilized.IsZero() {
  69. t.Fatalf("unexpected time")
  70. }
  71. select {
  72. case <-vn.Ring.ChanShutdown:
  73. return
  74. default:
  75. t.Fatalf("expected message")
  76. }
  77. }
  78. func TestVnodeStabilizeResched(t *testing.T) {
  79. vn := makeVnode()
  80. vn.Init(1)
  81. vn.Successors[0] = &vn.Vnode
  82. vn.Schedule()
  83. vn.Stabilize()
  84. if vn.Timer == nil {
  85. t.Fatalf("expected timer")
  86. }
  87. if vn.Stabilized.IsZero() {
  88. t.Fatalf("expected time")
  89. }
  90. vn.Timer.Stop()
  91. }
  92. func TestVnodeKnownSucc(t *testing.T) {
  93. vn := makeVnode()
  94. vn.Init(0)
  95. if vn.KnownSuccessors() != 0 {
  96. t.Fatalf("wrong num known!")
  97. }
  98. vn.Successors[0] = &chord.Vnode{Id: []byte{1}}
  99. if vn.KnownSuccessors() != 1 {
  100. t.Fatalf("wrong num known!")
  101. }
  102. }
  103. // Checks panic if no Successors
  104. func TestVnodeCheckNewSuccAlivePanic(t *testing.T) {
  105. defer func() {
  106. if r := recover(); r == nil {
  107. t.Fatalf("expected panic!")
  108. }
  109. }()
  110. vn1 := makeVnode()
  111. vn1.Init(1)
  112. vn1.CheckNewSuccessor()
  113. }
  114. // Checks pinging a live successor with no changes
  115. func TestVnodeCheckNewSuccAlive(t *testing.T) {
  116. vn1 := makeVnode()
  117. vn1.Init(1)
  118. vn2 := makeVnode()
  119. vn2.Ring = vn1.Ring
  120. vn2.Init(2)
  121. vn2.Predecessor = &vn1.Vnode
  122. vn1.Successors[0] = &vn2.Vnode
  123. if pred, _ := vn2.GetPredecessor(); pred != &vn1.Vnode {
  124. t.Fatalf("expected vn1 as predecessor")
  125. }
  126. if err := vn1.CheckNewSuccessor(); err != nil {
  127. t.Fatalf("unexpected err %s", err)
  128. }
  129. if vn1.Successors[0] != &vn2.Vnode {
  130. t.Fatalf("unexpected successor!")
  131. }
  132. }
  133. // Checks pinging a dead successor with no alternates
  134. func TestVnodeCheckNewSuccDead(t *testing.T) {
  135. vn1 := makeVnode()
  136. vn1.Init(1)
  137. vn1.Successors[0] = &chord.Vnode{Id: []byte{0}}
  138. if err := vn1.CheckNewSuccessor(); err == nil {
  139. t.Fatal("err!", err)
  140. }
  141. if vn1.Successors[0].String() != "00" {
  142. t.Fatalf("unexpected successor!")
  143. }
  144. }
  145. // Checks pinging a dead successor with alternate
  146. func TestVnodeCheckNewSuccDeadAlternate(t *testing.T) {
  147. r := makeRing()
  148. sort.Sort(r)
  149. vn1 := r.Vnodes[0]
  150. vn2 := r.Vnodes[1]
  151. vn3 := r.Vnodes[2]
  152. vn1.Successors[0] = &vn2.Vnode
  153. vn1.Successors[1] = &vn3.Vnode
  154. vn2.Predecessor = &vn1.Vnode
  155. vn3.Predecessor = &vn2.Vnode
  156. // Remove vn2
  157. (r.Transport.(*chord.LocalTransport)).Deregister(&vn2.Vnode)
  158. // Should not get an error
  159. if err := vn1.CheckNewSuccessor(); err != nil {
  160. t.Fatalf("unexpected err %s", err)
  161. }
  162. // Should become vn3
  163. if vn1.Successors[0] != &vn3.Vnode {
  164. t.Fatalf("unexpected successor!")
  165. }
  166. }
  167. // Checks pinging a dead successor with all dead alternates
  168. func TestVnodeCheckNewSuccAllDeadAlternates(t *testing.T) {
  169. r := makeRing()
  170. sort.Sort(r)
  171. vn1 := r.Vnodes[0]
  172. vn2 := r.Vnodes[1]
  173. vn3 := r.Vnodes[2]
  174. vn1.Successors[0] = &vn2.Vnode
  175. vn1.Successors[1] = &vn3.Vnode
  176. vn2.Predecessor = &vn1.Vnode
  177. vn3.Predecessor = &vn2.Vnode
  178. // Remove vn2
  179. (r.Transport.(*chord.LocalTransport)).Deregister(&vn2.Vnode)
  180. (r.Transport.(*chord.LocalTransport)).Deregister(&vn3.Vnode)
  181. // Should get an error
  182. if err := vn1.CheckNewSuccessor(); err.Error() != "All known Successors dead!" {
  183. t.Fatalf("unexpected err %s", err)
  184. }
  185. // Should just be vn3
  186. if vn1.Successors[0] != &vn3.Vnode {
  187. t.Fatalf("unexpected successor!")
  188. }
  189. }
  190. // Checks pinging a successor, and getting a new successor
  191. func TestVnodeCheckNewSuccNewSucc(t *testing.T) {
  192. r := makeRing()
  193. sort.Sort(r)
  194. vn1 := r.Vnodes[0]
  195. vn2 := r.Vnodes[1]
  196. vn3 := r.Vnodes[2]
  197. vn1.Successors[0] = &vn3.Vnode
  198. vn2.Predecessor = &vn1.Vnode
  199. vn3.Predecessor = &vn2.Vnode
  200. // vn3 pred is vn2
  201. if pred, _ := vn3.GetPredecessor(); pred != &vn2.Vnode {
  202. t.Fatalf("expected vn2 as predecessor")
  203. }
  204. // Should not get an error
  205. if err := vn1.CheckNewSuccessor(); err != nil {
  206. t.Fatalf("unexpected err %s", err)
  207. }
  208. // Should become vn2
  209. if vn1.Successors[0] != &vn2.Vnode {
  210. t.Fatalf("unexpected successor! %s", vn1.Successors[0])
  211. }
  212. // 2nd successor should become vn3
  213. if vn1.Successors[1] != &vn3.Vnode {
  214. t.Fatalf("unexpected 2nd successor!")
  215. }
  216. }
  217. // Checks pinging a successor, and getting a new successor
  218. // which is not alive
  219. func TestVnodeCheckNewSuccNewSuccDead(t *testing.T) {
  220. r := makeRing()
  221. sort.Sort(r)
  222. vn1 := r.Vnodes[0]
  223. vn2 := r.Vnodes[1]
  224. vn3 := r.Vnodes[2]
  225. vn1.Successors[0] = &vn3.Vnode
  226. vn2.Predecessor = &vn1.Vnode
  227. vn3.Predecessor = &vn2.Vnode
  228. // Remove vn2
  229. (r.Transport.(*chord.LocalTransport)).Deregister(&vn2.Vnode)
  230. // Should not get an error
  231. if err := vn1.CheckNewSuccessor(); err != nil {
  232. t.Fatalf("unexpected err %s", err)
  233. }
  234. // Should stay vn3
  235. if vn1.Successors[0] != &vn3.Vnode {
  236. t.Fatalf("unexpected successor!")
  237. }
  238. }
  239. // Test notifying a successor successfully
  240. func TestVnodeNotifySucc(t *testing.T) {
  241. r := makeRing()
  242. sort.Sort(r)
  243. s1 := &chord.Vnode{Id: []byte{1}}
  244. s2 := &chord.Vnode{Id: []byte{2}}
  245. s3 := &chord.Vnode{Id: []byte{3}}
  246. vn1 := r.Vnodes[0]
  247. vn2 := r.Vnodes[1]
  248. vn1.Successors[0] = &vn2.Vnode
  249. vn2.Predecessor = &vn1.Vnode
  250. vn2.Successors[0] = s1
  251. vn2.Successors[1] = s2
  252. vn2.Successors[2] = s3
  253. // Should get no error
  254. if err := vn1.NotifySuccessor(); err != nil {
  255. t.Fatalf("unexpected err %s", err)
  256. }
  257. // Successor list should be updated
  258. if vn1.Successors[1] != s1 {
  259. t.Fatalf("bad succ 1")
  260. }
  261. if vn1.Successors[2] != s2 {
  262. t.Fatalf("bad succ 2")
  263. }
  264. if vn1.Successors[3] != s3 {
  265. t.Fatalf("bad succ 3")
  266. }
  267. // Predecessor should not updated
  268. if vn2.Predecessor != &vn1.Vnode {
  269. t.Fatalf("bad predecessor")
  270. }
  271. }
  272. // Test notifying a dead successor
  273. func TestVnodeNotifySuccDead(t *testing.T) {
  274. r := makeRing()
  275. sort.Sort(r)
  276. vn1 := r.Vnodes[0]
  277. vn2 := r.Vnodes[1]
  278. vn1.Successors[0] = &vn2.Vnode
  279. vn2.Predecessor = &vn1.Vnode
  280. // Remove vn2
  281. (r.Transport.(*chord.LocalTransport)).Deregister(&vn2.Vnode)
  282. // Should get error
  283. if err := vn1.NotifySuccessor(); err == nil {
  284. t.Fatalf("expected err!")
  285. }
  286. }
  287. func TestVnodeNotifySamePred(t *testing.T) {
  288. r := makeRing()
  289. sort.Sort(r)
  290. s1 := &chord.Vnode{Id: []byte{1}}
  291. s2 := &chord.Vnode{Id: []byte{2}}
  292. s3 := &chord.Vnode{Id: []byte{3}}
  293. vn1 := r.Vnodes[0]
  294. vn2 := r.Vnodes[1]
  295. vn1.Successors[0] = &vn2.Vnode
  296. vn2.Predecessor = &vn1.Vnode
  297. vn2.Successors[0] = s1
  298. vn2.Successors[1] = s2
  299. vn2.Successors[2] = s3
  300. succs, err := vn2.Notify(&vn1.Vnode)
  301. if err != nil {
  302. t.Fatalf("unexpected error! %s", err)
  303. }
  304. if succs[0] != s1 {
  305. t.Fatalf("unexpected succ 0")
  306. }
  307. if succs[1] != s2 {
  308. t.Fatalf("unexpected succ 1")
  309. }
  310. if succs[2] != s3 {
  311. t.Fatalf("unexpected succ 2")
  312. }
  313. if vn2.Predecessor != &vn1.Vnode {
  314. t.Fatalf("unexpected pred")
  315. }
  316. }
  317. func TestVnodeNotifyNoPred(t *testing.T) {
  318. r := makeRing()
  319. sort.Sort(r)
  320. s1 := &chord.Vnode{Id: []byte{1}}
  321. s2 := &chord.Vnode{Id: []byte{2}}
  322. s3 := &chord.Vnode{Id: []byte{3}}
  323. vn1 := r.Vnodes[0]
  324. vn2 := r.Vnodes[1]
  325. vn2.Successors[0] = s1
  326. vn2.Successors[1] = s2
  327. vn2.Successors[2] = s3
  328. succs, err := vn2.Notify(&vn1.Vnode)
  329. if err != nil {
  330. t.Fatalf("unexpected error! %s", err)
  331. }
  332. if succs[0] != s1 {
  333. t.Fatalf("unexpected succ 0")
  334. }
  335. if succs[1] != s2 {
  336. t.Fatalf("unexpected succ 1")
  337. }
  338. if succs[2] != s3 {
  339. t.Fatalf("unexpected succ 2")
  340. }
  341. if vn2.Predecessor != &vn1.Vnode {
  342. t.Fatalf("unexpected pred")
  343. }
  344. }
  345. func TestVnodeNotifyNewPred(t *testing.T) {
  346. r := makeRing()
  347. sort.Sort(r)
  348. vn1 := r.Vnodes[0]
  349. vn2 := r.Vnodes[1]
  350. vn3 := r.Vnodes[2]
  351. vn3.Predecessor = &vn1.Vnode
  352. _, err := vn3.Notify(&vn2.Vnode)
  353. if err != nil {
  354. t.Fatalf("unexpected error! %s", err)
  355. }
  356. if vn3.Predecessor != &vn2.Vnode {
  357. t.Fatalf("unexpected pred")
  358. }
  359. }
  360. func TestVnodeFixFinger(t *testing.T) {
  361. r := makeRing()
  362. sort.Sort(r)
  363. num := len(r.Vnodes)
  364. for i := 0; i < num; i++ {
  365. r.Vnodes[i].Init(i)
  366. r.Vnodes[i].Successors[0] = &r.Vnodes[(i+1)%num].Vnode
  367. }
  368. // Fix finger should not error
  369. vn := r.Vnodes[0]
  370. if err := vn.FixFingerTable(); err != nil {
  371. t.Fatalf("unexpected err, %s", err)
  372. }
  373. // Check we've progressed
  374. if vn.LastFinger != 158 {
  375. t.Fatalf("unexpected last finger! %d", vn.LastFinger)
  376. }
  377. // Ensure that we've setup our successor as the initial entries
  378. for i := 0; i < vn.LastFinger; i++ {
  379. if vn.Finger[i] != vn.Successors[0] {
  380. t.Fatalf("unexpected finger entry!")
  381. }
  382. }
  383. // Fix next index
  384. if err := vn.FixFingerTable(); err != nil {
  385. t.Fatalf("unexpected err, %s", err)
  386. }
  387. if vn.LastFinger != 0 {
  388. t.Fatalf("unexpected last finger! %d", vn.LastFinger)
  389. }
  390. }
  391. func TestVnodeCheckPredNoPred(t *testing.T) {
  392. v := makeVnode()
  393. v.Init(0)
  394. if err := v.CheckPredecessor(); err != nil {
  395. t.Fatalf("unpexected err! %s", err)
  396. }
  397. }
  398. func TestVnodeCheckLivePred(t *testing.T) {
  399. r := makeRing()
  400. sort.Sort(r)
  401. vn1 := r.Vnodes[0]
  402. vn2 := r.Vnodes[1]
  403. vn2.Predecessor = &vn1.Vnode
  404. if err := vn2.CheckPredecessor(); err != nil {
  405. t.Fatalf("unexpected error! %s", err)
  406. }
  407. if vn2.Predecessor != &vn1.Vnode {
  408. t.Fatalf("unexpected pred")
  409. }
  410. }
  411. func TestVnodeCheckDeadPred(t *testing.T) {
  412. r := makeRing()
  413. sort.Sort(r)
  414. vn1 := r.Vnodes[0]
  415. vn2 := r.Vnodes[1]
  416. vn2.Predecessor = &vn1.Vnode
  417. // Deregister vn1
  418. (r.Transport.(*chord.LocalTransport)).Deregister(&vn1.Vnode)
  419. if err := vn2.CheckPredecessor(); err != nil {
  420. t.Fatalf("unexpected error! %s", err)
  421. }
  422. if vn2.Predecessor != nil {
  423. t.Fatalf("unexpected pred")
  424. }
  425. }
  426. func TestVnodeFindSuccessors(t *testing.T) {
  427. r := makeRing()
  428. sort.Sort(r)
  429. num := len(r.Vnodes)
  430. for i := 0; i < num; i++ {
  431. r.Vnodes[i].Successors[0] = &r.Vnodes[(i+1)%num].Vnode
  432. }
  433. // Get a random key
  434. h := r.Config.HashFunc()
  435. h.Write([]byte("test"))
  436. key := h.Sum(nil)
  437. // Local only, should be nearest in the ring
  438. nearest := r.NearestVnode(key)
  439. exp := nearest.Successors[0]
  440. // Do a lookup on the key
  441. for i := 0; i < len(r.Vnodes); i++ {
  442. vn := r.Vnodes[i]
  443. succ, err := vn.FindSuccessors(1, key)
  444. if err != nil {
  445. t.Fatalf("unexpected err! %s", err)
  446. }
  447. // Local only, should be nearest in the ring
  448. if exp != succ[0] {
  449. t.Fatalf("unexpected succ! K:%x Exp: %s Got:%s",
  450. key, exp, succ[0])
  451. }
  452. }
  453. }
  454. // Ensure each node has multiple Successors
  455. func TestVnodeFindSuccessorsMultSucc(t *testing.T) {
  456. r := makeRing()
  457. sort.Sort(r)
  458. num := len(r.Vnodes)
  459. for i := 0; i < num; i++ {
  460. r.Vnodes[i].Successors[0] = &r.Vnodes[(i+1)%num].Vnode
  461. r.Vnodes[i].Successors[1] = &r.Vnodes[(i+2)%num].Vnode
  462. r.Vnodes[i].Successors[2] = &r.Vnodes[(i+3)%num].Vnode
  463. }
  464. // Get a random key
  465. h := r.Config.HashFunc()
  466. h.Write([]byte("test"))
  467. key := h.Sum(nil)
  468. // Local only, should be nearest in the ring
  469. nearest := r.NearestVnode(key)
  470. exp := nearest.Successors[0]
  471. // Do a lookup on the key
  472. for i := 0; i < len(r.Vnodes); i++ {
  473. vn := r.Vnodes[i]
  474. succ, err := vn.FindSuccessors(1, key)
  475. if err != nil {
  476. t.Fatalf("unexpected err! %s", err)
  477. }
  478. // Local only, should be nearest in the ring
  479. if exp != succ[0] {
  480. t.Fatalf("unexpected succ! K:%x Exp: %s Got:%s",
  481. key, exp, succ[0])
  482. }
  483. }
  484. }
  485. // Kill off a part of the ring and see what happens
  486. func TestVnodeFindSuccessorsSomeDead(t *testing.T) {
  487. r := makeRing()
  488. sort.Sort(r)
  489. num := len(r.Vnodes)
  490. for i := 0; i < num; i++ {
  491. r.Vnodes[i].Successors[0] = &r.Vnodes[(i+1)%num].Vnode
  492. r.Vnodes[i].Successors[1] = &r.Vnodes[(i+2)%num].Vnode
  493. }
  494. // Kill 2 of the nodes
  495. (r.Transport.(*chord.LocalTransport)).Deregister(&r.Vnodes[0].Vnode)
  496. (r.Transport.(*chord.LocalTransport)).Deregister(&r.Vnodes[3].Vnode)
  497. // Get a random key
  498. h := r.Config.HashFunc()
  499. h.Write([]byte("test"))
  500. key := h.Sum(nil)
  501. // Local only, should be nearest in the ring
  502. nearest := r.NearestVnode(key)
  503. exp := nearest.Successors[0]
  504. // Do a lookup on the key
  505. for i := 0; i < len(r.Vnodes); i++ {
  506. vn := r.Vnodes[i]
  507. succ, err := vn.FindSuccessors(1, key)
  508. if err != nil {
  509. t.Fatalf("(%d) unexpected err! %s", i, err)
  510. }
  511. // Local only, should be nearest in the ring
  512. if exp != succ[0] {
  513. t.Fatalf("(%d) unexpected succ! K:%x Exp: %s Got:%s",
  514. i, key, exp, succ[0])
  515. }
  516. }
  517. }
  518. func TestVnodeClearPred(t *testing.T) {
  519. v := makeVnode()
  520. v.Init(0)
  521. p := &chord.Vnode{Id: []byte{12}}
  522. v.Predecessor = p
  523. v.ClearPredecessor(p)
  524. if v.Predecessor != nil {
  525. t.Fatalf("expect no predecessor!")
  526. }
  527. np := &chord.Vnode{Id: []byte{14}}
  528. v.Predecessor = p
  529. v.ClearPredecessor(np)
  530. if v.Predecessor != p {
  531. t.Fatalf("expect p predecessor!")
  532. }
  533. }
  534. func TestVnodeSkipSucc(t *testing.T) {
  535. v := makeVnode()
  536. v.Init(0)
  537. s1 := &chord.Vnode{Id: []byte{10}}
  538. s2 := &chord.Vnode{Id: []byte{11}}
  539. s3 := &chord.Vnode{Id: []byte{12}}
  540. v.Successors[0] = s1
  541. v.Successors[1] = s2
  542. v.Successors[2] = s3
  543. // s2 should do nothing
  544. if err := v.SkipSuccessor(s2); err != nil {
  545. t.Fatalf("unexpected err")
  546. }
  547. if v.Successors[0] != s1 {
  548. t.Fatalf("unexpected suc")
  549. }
  550. // s1 should skip
  551. if err := v.SkipSuccessor(s1); err != nil {
  552. t.Fatalf("unexpected err")
  553. }
  554. if v.Successors[0] != s2 {
  555. t.Fatalf("unexpected suc")
  556. }
  557. if v.KnownSuccessors() != 2 {
  558. t.Fatalf("bad num of suc")
  559. }
  560. }
  561. func TestVnodeLeave(t *testing.T) {
  562. r := makeRing()
  563. sort.Sort(r)
  564. num := len(r.Vnodes)
  565. for i := int(0); i < num; i++ {
  566. r.Vnodes[i].Predecessor = &r.Vnodes[(i+num-1)%num].Vnode
  567. r.Vnodes[i].Successors[0] = &r.Vnodes[(i+1)%num].Vnode
  568. r.Vnodes[i].Successors[1] = &r.Vnodes[(i+2)%num].Vnode
  569. }
  570. // Make node 0 leave
  571. if err := r.Vnodes[0].Leave(); err != nil {
  572. t.Fatalf("unexpected err")
  573. }
  574. if r.Vnodes[4].Successors[0] != &r.Vnodes[1].Vnode {
  575. t.Fatalf("unexpected suc!")
  576. }
  577. if r.Vnodes[1].Predecessor != nil {
  578. t.Fatalf("unexpected pred!")
  579. }
  580. }