influxdb/test.go

178 lines
4.3 KiB
Go

package raft
import (
"fmt"
"io/ioutil"
"os"
"time"
)
const (
testHeartbeatTimeout = 20 * time.Millisecond
testElectionTimeout = 60 * time.Millisecond
)
func init() {
RegisterCommand(&joinCommand{})
RegisterCommand(&TestCommand1{})
RegisterCommand(&TestCommand2{})
}
//------------------------------------------------------------------------------
//
// Helpers
//
//------------------------------------------------------------------------------
//--------------------------------------
// Logs
//--------------------------------------
func getLogPath() string {
f, _ := ioutil.TempFile("", "raft-log-")
f.Close()
os.Remove(f.Name())
return f.Name()
}
func setupLogFile(content string) string {
f, _ := ioutil.TempFile("", "raft-log-")
f.Write([]byte(content))
f.Close()
return f.Name()
}
func setupLog(content string) (*Log, string) {
path := setupLogFile(content)
log := NewLog()
log.ApplyFunc = func(c Command) ([]byte, error) {
return nil, nil
}
if err := log.Open(path); err != nil {
panic("Unable to open log")
}
return log, path
}
//--------------------------------------
// Servers
//--------------------------------------
func newTestServer(name string, transporter Transporter) *Server {
path, _ := ioutil.TempDir("", "raft-server-")
server, _ := NewServer(name, path, transporter, nil)
return server
}
func newTestServerWithLog(name string, transporter Transporter, content string) *Server {
server := newTestServer(name, transporter)
ioutil.WriteFile(server.LogPath(), []byte(content), 0644)
return server
}
func newTestCluster(names []string, transporter Transporter, lookup map[string]*Server) []*Server {
servers := []*Server{}
for _, name := range names {
if lookup[name] != nil {
panic(fmt.Sprintf("raft: Duplicate server in test cluster! %v", name))
}
server := newTestServer(name, transporter)
server.SetElectionTimeout(testElectionTimeout)
servers = append(servers, server)
lookup[name] = server
}
for _, server := range servers {
server.SetHeartbeatTimeout(testHeartbeatTimeout)
for _, peer := range servers {
server.AddPeer(peer.Name())
}
server.Start()
}
return servers
}
//--------------------------------------
// Transporter
//--------------------------------------
type testTransporter struct {
sendVoteRequestFunc func(server *Server, peer *Peer, req *RequestVoteRequest) (*RequestVoteResponse, error)
sendAppendEntriesRequestFunc func(server *Server, peer *Peer, req *AppendEntriesRequest) (*AppendEntriesResponse, error)
sendSnapshotRequestFunc func(server *Server, peer *Peer, req *SnapshotRequest) (*SnapshotResponse, error)
}
func (t *testTransporter) SendVoteRequest(server *Server, peer *Peer, req *RequestVoteRequest) (*RequestVoteResponse, error) {
return t.sendVoteRequestFunc(server, peer, req)
}
func (t *testTransporter) SendAppendEntriesRequest(server *Server, peer *Peer, req *AppendEntriesRequest) (*AppendEntriesResponse, error) {
return t.sendAppendEntriesRequestFunc(server, peer, req)
}
func (t *testTransporter) SendSnapshotRequest(server *Server, peer *Peer, req *SnapshotRequest) (*SnapshotResponse, error) {
return t.sendSnapshotRequestFunc(server, peer, req)
}
type testStateMachine struct {
saveFunc func() ([]byte, error)
recoveryFunc func([]byte) error
}
func (sm *testStateMachine) Save() ([]byte, error) {
return sm.saveFunc()
}
func (sm *testStateMachine) Recovery(state []byte) error {
return sm.recoveryFunc(state)
}
//--------------------------------------
// Join Command
//--------------------------------------
type joinCommand struct {
Name string `json:"name"`
}
func (c *joinCommand) CommandName() string {
return "test:join"
}
func (c *joinCommand) Apply(server *Server) ([]byte, error) {
err := server.AddPeer(c.Name)
return nil, err
}
//--------------------------------------
// Command1
//--------------------------------------
type TestCommand1 struct {
Val string `json:"val"`
I int `json:"i"`
}
func (c TestCommand1) CommandName() string {
return "cmd_1"
}
func (c TestCommand1) Apply(server *Server) ([]byte, error) {
return nil, nil
}
//--------------------------------------
// Command2
//--------------------------------------
type TestCommand2 struct {
X int `json:"x"`
}
func (c TestCommand2) CommandName() string {
return "cmd_2"
}
func (c TestCommand2) Apply(server *Server) ([]byte, error) {
return nil, nil
}