1
0
Fork 0

Fix Store-level unit tests

master
Philip O'Toole 2 years ago
parent b03ed99eda
commit 89b132ac26

@ -1068,6 +1068,10 @@ func (m *MockStore) Query(qr *command.QueryRequest) ([]*command.QueryRows, error
return nil, nil
}
func (m *MockStore) Load(lr *command.LoadRequest) error {
return nil
}
func (m *MockStore) Join(id, addr string, voter bool) error {
return nil
}

@ -844,6 +844,8 @@ func (s *Store) Backup(leader bool, fmt BackupFormat, dst io.Writer) error {
return nil
}
// Loads an entire SQLite file into the database, sending the request
// through the Raft log.
func (s *Store) Load(lr *command.LoadRequest) error {
startT := time.Now()

@ -441,7 +441,6 @@ func Test_SingleNodeSQLitePath(t *testing.T) {
if !pathExists(path) {
t.Fatalf("SQLite file does not exist at %s", path)
}
}
func Test_SingleNodeBackupBinary(t *testing.T) {
@ -545,7 +544,7 @@ COMMIT;
}
}
func Test_SingleNodeLoad(t *testing.T) {
func Test_SingleNodeSingleCommandTrigger(t *testing.T) {
s, ln := mustNewStore(true)
defer os.RemoveAll(s.Path())
defer ln.Close()
@ -563,31 +562,35 @@ func Test_SingleNodeLoad(t *testing.T) {
dump := `PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE foo (id integer not null primary key, name text);
INSERT INTO "foo" VALUES(1,'fiona');
CREATE TABLE foo (id integer primary key asc, name text);
INSERT INTO "foo" VALUES(1,'bob');
INSERT INTO "foo" VALUES(2,'alice');
INSERT INTO "foo" VALUES(3,'eve');
CREATE TABLE bar (nameid integer, age integer);
INSERT INTO "bar" VALUES(1,44);
INSERT INTO "bar" VALUES(2,46);
INSERT INTO "bar" VALUES(3,8);
CREATE VIEW foobar as select name as Person, Age as age from foo inner join bar on foo.id == bar.nameid;
CREATE TRIGGER new_foobar instead of insert on foobar begin insert into foo (name) values (new.Person); insert into bar (nameid, age) values ((select id from foo where name == new.Person), new.Age); end;
COMMIT;
`
_, err := s.Execute(executeRequestFromString(dump, false, false))
if err != nil {
t.Fatalf("failed to load simple dump: %s", err.Error())
t.Fatalf("failed to load dump with trigger: %s", err.Error())
}
// Check that data were loaded correctly.
qr := queryRequestFromString("SELECT * FROM foo", false, true)
qr.Level = command.QueryRequest_QUERY_REQUEST_LEVEL_STRONG
r, err := s.Query(qr)
// Check that the VIEW and TRIGGER are OK by using both.
er := executeRequestFromString("INSERT INTO foobar VALUES('jason', 16)", false, true)
r, err := s.Execute(er)
if err != nil {
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := `["id","name"]`, asJSON(r[0].Columns); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
t.Fatalf("failed to insert into view on single node: %s", err.Error())
}
if exp, got := `[[1,"fiona"]]`, asJSON(r[0].Values); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
if exp, got := int64(3), r[0].GetLastInsertId(); exp != got {
t.Fatalf("unexpected results for query\nexp: %d\ngot: %d", exp, got)
}
}
func Test_SingleNodeSingleCommandTrigger(t *testing.T) {
func Test_SingleNodeLoadText(t *testing.T) {
s, ln := mustNewStore(true)
defer os.RemoveAll(s.Path())
defer ln.Close()
@ -605,35 +608,31 @@ func Test_SingleNodeSingleCommandTrigger(t *testing.T) {
dump := `PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE foo (id integer primary key asc, name text);
INSERT INTO "foo" VALUES(1,'bob');
INSERT INTO "foo" VALUES(2,'alice');
INSERT INTO "foo" VALUES(3,'eve');
CREATE TABLE bar (nameid integer, age integer);
INSERT INTO "bar" VALUES(1,44);
INSERT INTO "bar" VALUES(2,46);
INSERT INTO "bar" VALUES(3,8);
CREATE VIEW foobar as select name as Person, Age as age from foo inner join bar on foo.id == bar.nameid;
CREATE TRIGGER new_foobar instead of insert on foobar begin insert into foo (name) values (new.Person); insert into bar (nameid, age) values ((select id from foo where name == new.Person), new.Age); end;
CREATE TABLE foo (id integer not null primary key, name text);
INSERT INTO "foo" VALUES(1,'fiona');
COMMIT;
`
_, err := s.Execute(executeRequestFromString(dump, false, false))
if err != nil {
t.Fatalf("failed to load dump with trigger: %s", err.Error())
t.Fatalf("failed to load simple dump: %s", err.Error())
}
// Check that the VIEW and TRIGGER are OK by using both.
er := executeRequestFromString("INSERT INTO foobar VALUES('jason', 16)", false, true)
r, err := s.Execute(er)
// Check that data were loaded correctly.
qr := queryRequestFromString("SELECT * FROM foo", false, true)
qr.Level = command.QueryRequest_QUERY_REQUEST_LEVEL_STRONG
r, err := s.Query(qr)
if err != nil {
t.Fatalf("failed to insert into view on single node: %s", err.Error())
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := int64(3), r[0].GetLastInsertId(); exp != got {
t.Fatalf("unexpected results for query\nexp: %d\ngot: %d", exp, got)
if exp, got := `["id","name"]`, asJSON(r[0].Columns); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
if exp, got := `[[1,"fiona"]]`, asJSON(r[0].Values); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
}
func Test_SingleNodeLoadNoStatements(t *testing.T) {
func Test_SingleNodeLoadTextNoStatements(t *testing.T) {
s, ln := mustNewStore(true)
defer os.RemoveAll(s.Path())
defer ln.Close()
@ -659,7 +658,7 @@ COMMIT;
}
}
func Test_SingleNodeLoadEmpty(t *testing.T) {
func Test_SingleNodeLoadTextEmpty(t *testing.T) {
s, ln := mustNewStore(true)
defer os.RemoveAll(s.Path())
defer ln.Close()
@ -682,7 +681,7 @@ func Test_SingleNodeLoadEmpty(t *testing.T) {
}
}
func Test_SingleNodeLoadChinook(t *testing.T) {
func Test_SingleNodeLoadTextChinook(t *testing.T) {
s, ln := mustNewStore(true)
defer os.RemoveAll(s.Path())
defer ln.Close()
@ -745,6 +744,54 @@ func Test_SingleNodeLoadChinook(t *testing.T) {
}
}
func Test_SingleNodeLoadBinary(t *testing.T) {
s, ln := mustNewStore(true)
defer os.RemoveAll(s.Path())
defer ln.Close()
if err := s.Open(); err != nil {
t.Fatalf("failed to open single-node store: %s", err.Error())
}
if err := s.Bootstrap(NewServer(s.ID(), s.Addr(), true)); err != nil {
t.Fatalf("failed to bootstrap single-node store: %s", err.Error())
}
defer s.Close(true)
if _, err := s.WaitForLeader(10 * time.Second); err != nil {
t.Fatalf("Error waiting for leader: %s", err)
}
err := s.Load(loadRequestFromFile(filepath.Join("testdata", "load.sqlite")))
if err != nil {
t.Fatalf("failed to load SQLite file: %s", err.Error())
}
// Check that data were loaded correctly.
qr := queryRequestFromString("SELECT * FROM foo WHERE id=2", false, true)
qr.Level = command.QueryRequest_QUERY_REQUEST_LEVEL_STRONG
r, err := s.Query(qr)
if err != nil {
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := `["id","name"]`, asJSON(r[0].Columns); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
if exp, got := `[[2,"fiona"]]`, asJSON(r[0].Values); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
qr = queryRequestFromString("SELECT count(*) FROM foo", false, true)
qr.Level = command.QueryRequest_QUERY_REQUEST_LEVEL_STRONG
r, err = s.Query(qr)
if err != nil {
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := `["count(*)"]`, asJSON(r[0].Columns); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
if exp, got := `[[3]]`, asJSON(r[0].Values); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
}
// Test_SingleNodeRecoverNoChange tests a node recovery that doesn't
// actually change anything.
func Test_SingleNodeRecoverNoChange(t *testing.T) {
@ -1943,6 +1990,14 @@ func mustWriteFile(path, contents string) {
}
}
func mustReadFile(path string) []byte {
b, err := ioutil.ReadFile(path)
if err != nil {
panic("failed to read file")
}
return b
}
func mustTempDir() string {
var err error
path, err := ioutil.TempDir("", "rqlilte-test-")
@ -2002,6 +2057,12 @@ func queryRequestFromStrings(s []string, timings, tx bool) *command.QueryRequest
}
}
func loadRequestFromFile(path string) *command.LoadRequest {
return &command.LoadRequest{
Data: mustReadFile(path),
}
}
// waitForLeaderID waits until the Store's LeaderID is set, or the timeout
// expires. Because setting Leader ID requires Raft to set the cluster
// configuration, it's not entirely deterministic when it will be set.

Binary file not shown.
Loading…
Cancel
Save