// startRaft starts a raft node from the given wal dir. // If the wal dir does not exist, startRaft will start a new raft node. // If the wal dir exists, startRaft will restart the previous raft node. // startRaft returns the started raft node and the opened wal. func startRaft(id int64, peerIDs []int64, waldir string) (raft.Node, *wal.WAL) { if !wal.Exist(waldir) { w, err := wal.Create(waldir) if err != nil { log.Fatal(err) } n := raft.Start(id, peerIDs, 10, 1) return n, w } // restart a node from previous wal // TODO(xiangli): check snapshot; not open from one w, err := wal.OpenAtIndex(waldir, 1) if err != nil { log.Fatal(err) } wid, st, ents, err := w.ReadAll() // TODO(xiangli): save/recovery nodeID? if wid != 0 { log.Fatalf("unexpected nodeid %d: nodeid should always be zero until we save nodeid into wal", wid) } if err != nil { log.Fatal(err) } n := raft.Restart(id, peerIDs, 10, 1, st, ents) return n, w }
func TestSet(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() st := store.New() n := raft.Start(1, []int64{1}, 0, 0) n.Campaign(ctx) srv := &etcdserver.Server{ Node: n, Store: st, Send: etcdserver.SendFunc(nopSend), Save: func(st raftpb.State, ents []raftpb.Entry) {}, } etcdserver.Start(srv) defer srv.Stop() h := Handler{ Timeout: time.Hour, Server: srv, } s := httptest.NewServer(h) defer s.Close() resp, err := http.PostForm(s.URL+"/v2/keys/foo", url.Values{"value": {"bar"}}) if err != nil { t.Fatal(err) } if resp.StatusCode != 201 { t.Errorf("StatusCode = %d, expected %d", 201, resp.StatusCode) } g := new(store.Event) if err := json.NewDecoder(resp.Body).Decode(&g); err != nil { t.Fatal(err) } w := &store.NodeExtern{ Key: "/foo/1", Value: stringp("bar"), ModifiedIndex: 1, CreatedIndex: 1, } if !reflect.DeepEqual(g.Node, w) { t.Errorf("g = %+v, want %+v", g.Node, w) } }
func testServer(t *testing.T, ns int64) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ss := make([]*Server, ns) send := func(msgs []raftpb.Message) { for _, m := range msgs { t.Logf("m = %+v\n", m) ss[m.To-1].Node.Step(ctx, m) } } peers := make([]int64, ns) for i := int64(0); i < ns; i++ { peers[i] = i + 1 } for i := int64(0); i < ns; i++ { id := i + 1 n := raft.Start(id, peers, 10, 1) tk := time.NewTicker(10 * time.Millisecond) defer tk.Stop() srv := &Server{ Node: n, Store: store.New(), Send: send, Save: func(_ raftpb.State, _ []raftpb.Entry) {}, Ticker: tk.C, } Start(srv) // TODO(xiangli): randomize election timeout // then remove this sleep. time.Sleep(1 * time.Millisecond) ss[i] = srv } for i := 1; i <= 10; i++ { r := pb.Request{ Method: "PUT", Id: int64(i), Path: "/foo", Val: "bar", } j := rand.Intn(len(ss)) t.Logf("ss = %d", j) resp, err := ss[j].Do(ctx, r) if err != nil { t.Fatal(err) } g, w := resp.Event.Node, &store.NodeExtern{ Key: "/foo", ModifiedIndex: uint64(i), CreatedIndex: uint64(i), Value: stringp("bar"), } if !reflect.DeepEqual(g, w) { t.Error("value:", *g.Value) t.Errorf("g = %+v, w %+v", g, w) } } time.Sleep(10 * time.Millisecond) var last interface{} for i, sv := range ss { sv.Stop() g, _ := sv.Store.Get("/", true, true) if last != nil && !reflect.DeepEqual(last, g) { t.Errorf("server %d: Root = %#v, want %#v", i, g, last) } last = g } }