From 3c5e31b25a53268b413bc1e511b7486a2a1c80b9 Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Wed, 8 Sep 2021 15:23:50 +0200 Subject: Renamed TrainStop to simply Stop --- pkg/database/migrations.go | 2 +- pkg/database/stop.go | 47 +++++++++++++++ pkg/database/stop_test.go | 130 ++++++++++++++++++++++++++++++++++++++++ pkg/database/train_stop.go | 47 --------------- pkg/database/train_stop_test.go | 130 ---------------------------------------- 5 files changed, 178 insertions(+), 178 deletions(-) create mode 100644 pkg/database/stop.go create mode 100644 pkg/database/stop_test.go delete mode 100644 pkg/database/train_stop.go delete mode 100644 pkg/database/train_stop_test.go (limited to 'pkg/database') diff --git a/pkg/database/migrations.go b/pkg/database/migrations.go index ada638a..c2f35dc 100644 --- a/pkg/database/migrations.go +++ b/pkg/database/migrations.go @@ -23,7 +23,7 @@ var allMigrations = []func(tx *sql.Tx) error{ created_at DATE DEFAULT (datetime('now')), FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); - CREATE TABLE train_stops ( + CREATE TABLE stops ( id TEXT PRIMARY KEY, name TEXT NOT NULL );` diff --git a/pkg/database/stop.go b/pkg/database/stop.go new file mode 100644 index 0000000..519b9aa --- /dev/null +++ b/pkg/database/stop.go @@ -0,0 +1,47 @@ +package database + +import ( + "git.adyxax.org/adyxax/trains/pkg/model" +) + +func (env *DBEnv) CountStops() (i int, err error) { + query := `SELECT count(*) from stops;` + err = env.db.QueryRow(query).Scan(&i) + if err != nil { + return 0, newQueryError("Could not run database query: most likely the schema is corrupted", err) + } + return +} + +func (env *DBEnv) ReplaceAndImportStops(trainStops []model.Stop) error { + pre_query := `DELETE FROM stops;` + query := ` + INSERT INTO stops + (id, name) + VALUES + ($1, $2);` + tx, err := env.db.Begin() + if err != nil { + return newTransactionError("Could not Begin()", err) + } + _, err = tx.Exec(pre_query) + if err != nil { + tx.Rollback() + return newQueryError("Could not run database query: most likely the schema is corrupted", err) + } + for i := 0; i < len(trainStops); i++ { + _, err = tx.Exec( + query, + trainStops[i].Id, + trainStops[i].Name, + ) + if err != nil { + tx.Rollback() + return newQueryError("Could not run database query", err) + } + } + if err := tx.Commit(); err != nil { + return newTransactionError("Could not commit transaction", err) + } + return nil +} diff --git a/pkg/database/stop_test.go b/pkg/database/stop_test.go new file mode 100644 index 0000000..7329ac7 --- /dev/null +++ b/pkg/database/stop_test.go @@ -0,0 +1,130 @@ +package database + +import ( + "reflect" + "testing" + + "git.adyxax.org/adyxax/trains/pkg/model" + "github.com/DATA-DOG/go-sqlmock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCountStops(t *testing.T) { + trainStops := []model.Stop{ + model.Stop{Id: "id1", Name: "name1"}, + model.Stop{Id: "id2", Name: "name2"}, + } + // test db setup + db, err := InitDB("sqlite3", "file::memory:?_foreign_keys=on") + require.NoError(t, err) + // check sql error + i, err := db.CountStops() + require.Error(t, err) + assert.Equalf(t, reflect.TypeOf(err), reflect.TypeOf(&QueryError{}), "Invalid error type. Got %s but expected %s", reflect.TypeOf(err), reflect.TypeOf(&QueryError{})) + // normal check + err = db.Migrate() + require.NoError(t, err) + err = db.ReplaceAndImportStops(trainStops) + i, err = db.CountStops() + require.NoError(t, err) + assert.Equal(t, i, len(trainStops)) +} + +func TestReplaceAndImportStops(t *testing.T) { + // test db setup + db, err := InitDB("sqlite3", "file::memory:?_foreign_keys=on") + require.NoError(t, err) + err = db.Migrate() + require.NoError(t, err) + // datasets + data1 := []model.Stop{ + model.Stop{Id: "first", Name: "firstName"}, + model.Stop{Id: "second", Name: "secondName"}, + } + data2 := []model.Stop{ + model.Stop{Id: "first", Name: "firstTest"}, + model.Stop{Id: "secondTest", Name: "secondTest"}, + model.Stop{Id: "thirdTest", Name: "thirdTest"}, + } + testCases := []struct { + name string + input []model.Stop + expectedError interface{} + }{ + {"Normal insert", data1, nil}, + {"Normal insert overwrite", data2, nil}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := db.ReplaceAndImportStops(tc.input) + if tc.expectedError != nil { + require.Error(t, err) + assert.Equalf(t, reflect.TypeOf(err), reflect.TypeOf(tc.expectedError), "Invalid error type. Got %s but expected %s", reflect.TypeOf(err), reflect.TypeOf(tc.expectedError)) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestReplaceAndImportStopsWithSQLMock(t *testing.T) { + // datasets + data1 := []model.Stop{ + model.Stop{Id: "first", Name: "firstName"}, + model.Stop{Id: "second", Name: "secondName"}, + } + // Transaction begin error + dbBeginError, _, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + defer dbBeginError.Close() + // Query error cannot delete from + dbCannotDeleteFrom, mockCannotDeleteFrom, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + defer dbCannotDeleteFrom.Close() + mockCannotDeleteFrom.ExpectBegin() + // Transaction commit error + dbCannotInsertError, mockCannotInsertError, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + defer dbCannotInsertError.Close() + mockCannotInsertError.ExpectBegin() + mockCannotInsertError.ExpectExec(`DELETE FROM`).WillReturnResult(sqlmock.NewResult(1, 1)) + // Transaction commit error + dbCommitError, mockCommitError, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + defer dbCommitError.Close() + mockCommitError.ExpectBegin() + mockCommitError.ExpectExec(`DELETE FROM`).WillReturnResult(sqlmock.NewResult(1, 1)) + mockCommitError.ExpectExec(`INSERT INTO`).WillReturnResult(sqlmock.NewResult(1, 1)) + mockCommitError.ExpectExec(`INSERT INTO`).WillReturnResult(sqlmock.NewResult(1, 1)) + // Test cases + testCases := []struct { + name string + db *DBEnv + expectedError interface{} + }{ + {"begin transaction error", &DBEnv{db: dbBeginError}, &TransactionError{}}, + {"query error cannot delete from", &DBEnv{db: dbCannotDeleteFrom}, &QueryError{}}, + {"query error cannot insert into", &DBEnv{db: dbCannotInsertError}, &QueryError{}}, + {"commit transaction error", &DBEnv{db: dbCommitError}, &TransactionError{}}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := tc.db.ReplaceAndImportStops(data1) + if tc.expectedError != nil { + require.Error(t, err) + assert.Equalf(t, reflect.TypeOf(err), reflect.TypeOf(tc.expectedError), "Invalid error type. Got %s but expected %s", reflect.TypeOf(err), reflect.TypeOf(tc.expectedError)) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/pkg/database/train_stop.go b/pkg/database/train_stop.go deleted file mode 100644 index ee7be00..0000000 --- a/pkg/database/train_stop.go +++ /dev/null @@ -1,47 +0,0 @@ -package database - -import ( - "git.adyxax.org/adyxax/trains/pkg/model" -) - -func (env *DBEnv) CountTrainStops() (i int, err error) { - query := `SELECT count(*) from train_stops;` - err = env.db.QueryRow(query).Scan(&i) - if err != nil { - return 0, newQueryError("Could not run database query: most likely the schema is corrupted", err) - } - return -} - -func (env *DBEnv) ReplaceAndImportTrainStops(trainStops []model.TrainStop) error { - pre_query := `DELETE FROM train_stops;` - query := ` - INSERT INTO train_stops - (id, name) - VALUES - ($1, $2);` - tx, err := env.db.Begin() - if err != nil { - return newTransactionError("Could not Begin()", err) - } - _, err = tx.Exec(pre_query) - if err != nil { - tx.Rollback() - return newQueryError("Could not run database query: most likely the schema is corrupted", err) - } - for i := 0; i < len(trainStops); i++ { - _, err = tx.Exec( - query, - trainStops[i].Id, - trainStops[i].Name, - ) - if err != nil { - tx.Rollback() - return newQueryError("Could not run database query", err) - } - } - if err := tx.Commit(); err != nil { - return newTransactionError("Could not commit transaction", err) - } - return nil -} diff --git a/pkg/database/train_stop_test.go b/pkg/database/train_stop_test.go deleted file mode 100644 index b3f9459..0000000 --- a/pkg/database/train_stop_test.go +++ /dev/null @@ -1,130 +0,0 @@ -package database - -import ( - "reflect" - "testing" - - "git.adyxax.org/adyxax/trains/pkg/model" - "github.com/DATA-DOG/go-sqlmock" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestCountTrainStops(t *testing.T) { - trainStops := []model.TrainStop{ - model.TrainStop{Id: "id1", Name: "name1"}, - model.TrainStop{Id: "id2", Name: "name2"}, - } - // test db setup - db, err := InitDB("sqlite3", "file::memory:?_foreign_keys=on") - require.NoError(t, err) - // check sql error - i, err := db.CountTrainStops() - require.Error(t, err) - assert.Equalf(t, reflect.TypeOf(err), reflect.TypeOf(&QueryError{}), "Invalid error type. Got %s but expected %s", reflect.TypeOf(err), reflect.TypeOf(&QueryError{})) - // normal check - err = db.Migrate() - require.NoError(t, err) - err = db.ReplaceAndImportTrainStops(trainStops) - i, err = db.CountTrainStops() - require.NoError(t, err) - assert.Equal(t, i, len(trainStops)) -} - -func TestReplaceAndImportTrainStops(t *testing.T) { - // test db setup - db, err := InitDB("sqlite3", "file::memory:?_foreign_keys=on") - require.NoError(t, err) - err = db.Migrate() - require.NoError(t, err) - // datasets - data1 := []model.TrainStop{ - model.TrainStop{Id: "first", Name: "firstName"}, - model.TrainStop{Id: "second", Name: "secondName"}, - } - data2 := []model.TrainStop{ - model.TrainStop{Id: "first", Name: "firstTest"}, - model.TrainStop{Id: "secondTest", Name: "secondTest"}, - model.TrainStop{Id: "thirdTest", Name: "thirdTest"}, - } - testCases := []struct { - name string - input []model.TrainStop - expectedError interface{} - }{ - {"Normal insert", data1, nil}, - {"Normal insert overwrite", data2, nil}, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - err := db.ReplaceAndImportTrainStops(tc.input) - if tc.expectedError != nil { - require.Error(t, err) - assert.Equalf(t, reflect.TypeOf(err), reflect.TypeOf(tc.expectedError), "Invalid error type. Got %s but expected %s", reflect.TypeOf(err), reflect.TypeOf(tc.expectedError)) - } else { - require.NoError(t, err) - } - }) - } -} - -func TestReplaceAndImportTrainStopsWithSQLMock(t *testing.T) { - // datasets - data1 := []model.TrainStop{ - model.TrainStop{Id: "first", Name: "firstName"}, - model.TrainStop{Id: "second", Name: "secondName"}, - } - // Transaction begin error - dbBeginError, _, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - defer dbBeginError.Close() - // Query error cannot delete from - dbCannotDeleteFrom, mockCannotDeleteFrom, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - defer dbCannotDeleteFrom.Close() - mockCannotDeleteFrom.ExpectBegin() - // Transaction commit error - dbCannotInsertError, mockCannotInsertError, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - defer dbCannotInsertError.Close() - mockCannotInsertError.ExpectBegin() - mockCannotInsertError.ExpectExec(`DELETE FROM`).WillReturnResult(sqlmock.NewResult(1, 1)) - // Transaction commit error - dbCommitError, mockCommitError, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - defer dbCommitError.Close() - mockCommitError.ExpectBegin() - mockCommitError.ExpectExec(`DELETE FROM`).WillReturnResult(sqlmock.NewResult(1, 1)) - mockCommitError.ExpectExec(`INSERT INTO`).WillReturnResult(sqlmock.NewResult(1, 1)) - mockCommitError.ExpectExec(`INSERT INTO`).WillReturnResult(sqlmock.NewResult(1, 1)) - // Test cases - testCases := []struct { - name string - db *DBEnv - expectedError interface{} - }{ - {"begin transaction error", &DBEnv{db: dbBeginError}, &TransactionError{}}, - {"query error cannot delete from", &DBEnv{db: dbCannotDeleteFrom}, &QueryError{}}, - {"query error cannot insert into", &DBEnv{db: dbCannotInsertError}, &QueryError{}}, - {"commit transaction error", &DBEnv{db: dbCommitError}, &TransactionError{}}, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - err := tc.db.ReplaceAndImportTrainStops(data1) - if tc.expectedError != nil { - require.Error(t, err) - assert.Equalf(t, reflect.TypeOf(err), reflect.TypeOf(tc.expectedError), "Invalid error type. Got %s but expected %s", reflect.TypeOf(err), reflect.TypeOf(tc.expectedError)) - } else { - require.NoError(t, err) - } - }) - } -} -- cgit v1.2.3