1
0
Fork 0

Add needed unit test

master
Philip O'Toole 8 months ago
parent d64ac21291
commit 64d03d1eac

@ -12,6 +12,98 @@ import (
"github.com/rqlite/rqlite/v8/command/proto"
)
// Test_MultiNodeSimple tests that a the core operation of a multi-node
// cluster works as expected. That is, with a two node cluster, writes
// actually replicate, and reads are consistent.
func Test_MultiNodeSimple(t *testing.T) {
s0, ln := mustNewStore(t)
defer ln.Close()
if err := s0.Open(); err != nil {
t.Fatalf("failed to open single-node store: %s", err.Error())
}
defer s0.Close(true)
if err := s0.Bootstrap(NewServer(s0.ID(), s0.Addr(), true)); err != nil {
t.Fatalf("failed to bootstrap single-node store: %s", err.Error())
}
if _, err := s0.WaitForLeader(10 * time.Second); err != nil {
t.Fatalf("Error waiting for leader: %s", err)
}
s1, ln1 := mustNewStore(t)
defer ln1.Close()
if err := s1.Open(); err != nil {
t.Fatalf("failed to open single-node store: %s", err.Error())
}
defer s1.Close(true)
if err := s0.Join(joinRequest(s1.ID(), s1.Addr(), true)); err != nil {
t.Fatalf("failed to join single-node store: %s", err.Error())
}
if _, err := s1.WaitForLeader(10 * time.Second); err != nil {
t.Fatalf("Error waiting for leader: %s", err)
}
// Write some data.
er := executeRequestFromStrings([]string{
`CREATE TABLE foo (id INTEGER NOT NULL PRIMARY KEY, name TEXT)`,
`INSERT INTO foo(id, name) VALUES(1, "fiona")`,
}, false, false)
_, err := s0.Execute(er)
if err != nil {
t.Fatalf("failed to execute on single node: %s", err.Error())
}
if _, err := s0.WaitForAppliedFSM(5 * time.Second); err != nil {
t.Fatalf("failed to wait for FSM to apply on leader")
}
testPoll(t, func() bool {
return s0.DBAppliedIndex() == s1.DBAppliedIndex()
}, 250*time.Millisecond, 3*time.Second)
// Now, do a NONE consistency query on each node, to actually confirm the data
// has been replicated.
testFn1 := func(t *testing.T, s *Store) {
qr := queryRequestFromString("SELECT * FROM foo", false, false)
qr.Level = proto.QueryRequest_QUERY_REQUEST_LEVEL_NONE
r, err := s.Query(qr)
if err != nil {
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := `[{"columns":["id","name"],"types":["integer","text"],"values":[[1,"fiona"]]}]`, asJSON(r); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
}
testFn1(t, s0)
testFn1(t, s1)
// Write another row using Request
rr := executeQueryRequestFromString("INSERT INTO foo(id, name) VALUES(2, 'fiona')", proto.QueryRequest_QUERY_REQUEST_LEVEL_STRONG, false, false)
_, err = s0.Request(rr)
if err != nil {
t.Fatalf("failed to execute on single node: %s", err.Error())
}
testPoll(t, func() bool {
return s0.DBAppliedIndex() == s1.DBAppliedIndex()
}, 250*time.Millisecond, 3*time.Second)
// Now, do a NONE consistency query on each node, to actually confirm the data
// has been replicated.
testFn2 := func(t *testing.T, s *Store) {
qr := queryRequestFromString("SELECT COUNT(*) FROM foo", false, false)
qr.Level = proto.QueryRequest_QUERY_REQUEST_LEVEL_NONE
r, err := s.Query(qr)
if err != nil {
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := `[{"columns":["COUNT(*)"],"types":["integer"],"values":[[2]]}]`, asJSON(r); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
}
testFn2(t, s0)
testFn2(t, s1)
}
// Test_MultiNodeSnapshot_ErrorMessage tests that a snapshot fails with a specific
// error message when the snapshot is attempted too soon after joining a cluster.
// Hashicorp Raft doesn't expose a typed error, so we have to check the error

Loading…
Cancel
Save