From c047c4d89dcd1556559c4e123379b97be1a80f42 Mon Sep 17 00:00:00 2001 From: Jim Date: Tue, 9 Nov 2021 11:58:57 -0500 Subject: [PATCH] refactor (db): Remove the internal/db test tables from the migrations (#1675) --- internal/db/read_writer_ext_test.go | 1 + internal/db/read_writer_test.go | 17 ++ .../migrations/oss/postgres/19/03_db.up.sql | 23 ++ internal/db/testing.go | 253 ++++++++++++++++++ internal/db/testing_test.go | 1 + internal/oplog/testing_test.go | 2 +- 6 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 internal/db/schema/migrations/oss/postgres/19/03_db.up.sql diff --git a/internal/db/read_writer_ext_test.go b/internal/db/read_writer_ext_test.go index 889ecdaaa..2405da075 100644 --- a/internal/db/read_writer_ext_test.go +++ b/internal/db/read_writer_ext_test.go @@ -19,6 +19,7 @@ func TestDb_Create_OnConflict(t *testing.T) { wrapper := db.TestWrapper(t) conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) + db.TestCreateTables(t, conn) // create initial user for on conflict tests id, err := db.NewPublicId("test-user") diff --git a/internal/db/read_writer_test.go b/internal/db/read_writer_test.go index 86eac489a..ed6d2dd91 100644 --- a/internal/db/read_writer_test.go +++ b/internal/db/read_writer_test.go @@ -26,6 +26,7 @@ import ( func TestDb_UpdateUnsetField(t *testing.T) { db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) rw := &Db{ underlying: db, } @@ -49,6 +50,7 @@ func TestDb_UpdateUnsetField(t *testing.T) { func TestDb_Update(t *testing.T) { db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) now := ×tamp.Timestamp{Timestamp: timestamppb.Now()} publicId, err := NewPublicId("testuser") require.NoError(t, err) @@ -626,6 +628,7 @@ func (u *testUserWithVet) VetForWrite(ctx context.Context, r Reader, opType OpTy func TestDb_Create(t *testing.T) { // intentionally not run with t.Parallel so we don't need to use DoTx for the Create tests db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) t.Run("simple", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := Db{underlying: db} @@ -801,6 +804,7 @@ func TestDb_Create(t *testing.T) { func TestDb_LookupByPublicId(t *testing.T) { t.Parallel() db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) t.Run("simple", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := Db{underlying: db} @@ -856,6 +860,7 @@ func TestDb_LookupByPublicId(t *testing.T) { func TestDb_LookupWhere(t *testing.T) { t.Parallel() db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) t.Run("simple", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := Db{underlying: db} @@ -907,6 +912,7 @@ func TestDb_LookupWhere(t *testing.T) { func TestDb_SearchWhere(t *testing.T) { t.Parallel() db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) knownUser := testUser(t, db, "zedUser", "", "") type args struct { @@ -1059,6 +1065,7 @@ func TestDb_Exec(t *testing.T) { t.Parallel() t.Run("update", func(t *testing.T) { db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) require := require.New(t) w := Db{underlying: db} id := testId(t) @@ -1078,6 +1085,7 @@ func TestDb_DoTx(t *testing.T) { t.Parallel() ctx := context.TODO() db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) t.Run("valid-with-10-retries", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := &Db{underlying: db} @@ -1250,6 +1258,7 @@ func TestDb_DoTx(t *testing.T) { func TestDb_Delete(t *testing.T) { db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) newUser := func() *db_test.TestUser { w := &Db{ underlying: db, @@ -1475,6 +1484,7 @@ func TestDb_Delete(t *testing.T) { func TestDb_ScanRows(t *testing.T) { t.Parallel() db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := Db{underlying: db} @@ -1502,6 +1512,7 @@ func TestDb_ScanRows(t *testing.T) { func TestDb_Query(t *testing.T) { t.Parallel() db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) rw := Db{underlying: db} @@ -1530,6 +1541,7 @@ func TestDb_Query(t *testing.T) { func TestDb_CreateItems(t *testing.T) { db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) testOplogResourceId := testId(t) createFn := func() []interface{} { @@ -1742,6 +1754,7 @@ func TestDb_CreateItems(t *testing.T) { func TestDb_DeleteItems(t *testing.T) { db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) testOplogResourceId := testId(t) createFn := func() []interface{} { @@ -2031,6 +2044,7 @@ func testScooterAccessory(t *testing.T, conn *DB, scooterId, accessoryId uint32) func TestDb_LookupById(t *testing.T) { t.Parallel() db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) scooter := testScooter(t, db, "", 0) user := testUser(t, db, "", "", "") accessory := testAccessory(t, db, "test accessory") @@ -2170,6 +2184,7 @@ func TestDb_LookupById(t *testing.T) { func TestDb_GetTicket(t *testing.T) { db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) type notReplayable struct{} tests := []struct { name string @@ -2229,6 +2244,7 @@ func TestDb_GetTicket(t *testing.T) { func TestDb_WriteOplogEntryWith(t *testing.T) { db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) w := Db{underlying: db} ticket, err := w.GetTicket(&db_test.TestUser{}) @@ -2959,6 +2975,7 @@ func TestDb_oplogMsgsForItems(t *testing.T) { func TestDb_lookupAfterWrite(t *testing.T) { t.Parallel() db, _ := TestSetup(t, "postgres") + TestCreateTables(t, db) scooter := testScooter(t, db, "", 0) user := testUser(t, db, "", "", "") type args struct { diff --git a/internal/db/schema/migrations/oss/postgres/19/03_db.up.sql b/internal/db/schema/migrations/oss/postgres/19/03_db.up.sql new file mode 100644 index 000000000..79409adc3 --- /dev/null +++ b/internal/db/schema/migrations/oss/postgres/19/03_db.up.sql @@ -0,0 +1,23 @@ +begin; + +-- remove the internal/db test tables from the migrations. + +drop table if exists db_test_user cascade; +drop table if exists db_test_car cascade; +drop table if exists db_test_rental cascade; +drop table if exists db_test_scooter cascade; +drop table if exists db_test_accessory cascade; +drop table if exists db_test_scooter_accessory cascade; + + +delete from oplog_ticket where name in +( + 'db_test_user', + 'db_test_car', + 'db_test_rental', + 'db_test_scooter', + 'db_test_accessory', + 'db_test_scooter_accessory' +); + +commit; diff --git a/internal/db/testing.go b/internal/db/testing.go index 2fe197255..6a5eaf853 100644 --- a/internal/db/testing.go +++ b/internal/db/testing.go @@ -17,6 +17,7 @@ import ( wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-kms-wrapping/wrappers/aead" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gorm.io/gorm/logger" ) @@ -227,3 +228,255 @@ func WithTemplate(template string) TestOption { o.withTemplate = template } } + +// TestCreateTables will create the test tables for the db pkg +func TestCreateTables(t *testing.T, conn *DB) { + t.Helper() + t.Cleanup(func() { testDropTables(t, conn) }) + require := require.New(t) + testCtx := context.Background() + rw := New(conn) + _, err := rw.Exec(testCtx, testQueryCreateTables, nil) + require.NoError(err) + _, err = rw.Exec(testCtx, testQueryAddOplogEntries, nil) + require.NoError(err) +} + +func testDropTables(t *testing.T, conn *DB) { + t.Helper() + require := require.New(t) + testCtx := context.Background() + rw := New(conn) + _, err := rw.Exec(testCtx, testQueryDropTables, nil) + require.NoError(err) + _, err = rw.Exec(testCtx, testQueryDeleteOplogEntries, nil) + require.NoError(err) +} + +const ( + testQueryCreateTables = ` +begin; + +-- create test tables used in the unit tests for the internal/db package +-- these tables (db_test_user, db_test_car, db_test_rental, db_test_scooter) are +-- not part of the boundary domain model... they are simply used for testing +-- the internal/db package +create table if not exists db_test_user ( + id bigint generated always as identity primary key, + create_time wt_timestamp, + update_time wt_timestamp, + public_id text not null unique, + name text unique, + phone_number text, + email text, + version wt_version +); + +create trigger + update_time_column +before +update on db_test_user + for each row execute procedure update_time_column(); + +-- define the immutable fields for db_test_user +create trigger + immutable_columns +before +update on db_test_user + for each row execute procedure immutable_columns('create_time'); + +create trigger + default_create_time_column +before +insert on db_test_user + for each row execute procedure default_create_time(); + +create trigger + update_version_column +after update on db_test_user + for each row execute procedure update_version_column(); + +create table if not exists db_test_car ( + id bigint generated always as identity primary key, + create_time wt_timestamp, + update_time wt_timestamp, + public_id text not null unique, + name text unique, + model text, + mpg smallint +); + +create trigger + update_time_column +before +update on db_test_car + for each row execute procedure update_time_column(); + +-- define the immutable fields for db_test_car +create trigger + immutable_columns +before +update on db_test_car + for each row execute procedure immutable_columns('create_time'); + +create trigger + default_create_time_column +before +insert on db_test_car + for each row execute procedure default_create_time(); + +create table if not exists db_test_rental ( + id bigint generated always as identity primary key, + create_time wt_timestamp, + update_time wt_timestamp, + public_id text not null unique, + name text unique, + user_id bigint not null references db_test_user(id), + car_id bigint not null references db_test_car(id) +); + +create trigger + update_time_column +before +update on db_test_rental + for each row execute procedure update_time_column(); + +-- define the immutable fields for db_test_rental +create trigger + immutable_columns +before +update on db_test_rental + for each row execute procedure immutable_columns('create_time'); + +create trigger + default_create_time_column +before +insert on db_test_rental + for each row execute procedure default_create_time(); + + +create table if not exists db_test_scooter ( + id bigint generated always as identity primary key, + create_time wt_timestamp, + update_time wt_timestamp, + private_id text not null unique, + name text unique, + model text, + mpg smallint +); + +create trigger + update_time_column +before +update on db_test_scooter + for each row execute procedure update_time_column(); + + +-- define the immutable fields for db_test_scooter +create trigger + immutable_columns +before +update on db_test_scooter + for each row execute procedure immutable_columns('create_time'); + +create trigger + default_create_time_column +before +insert on db_test_scooter + for each row execute procedure default_create_time(); + +create table if not exists db_test_accessory ( + accessory_id bigint generated always as identity primary key, + create_time wt_timestamp, + update_time wt_timestamp, + description text not null +); + +create trigger + update_time_column +before +update on db_test_accessory + for each row execute procedure update_time_column(); + +create trigger + immutable_columns +before +update on db_test_accessory + for each row execute procedure immutable_columns('create_time'); + +create trigger + default_create_time_column +before +insert on db_test_accessory + for each row execute procedure default_create_time(); + + +create table if not exists db_test_scooter_accessory ( + accessory_id bigint references db_test_accessory(accessory_id), + scooter_id bigint references db_test_scooter(id), + create_time wt_timestamp, + update_time wt_timestamp, + review text, + primary key(accessory_id, scooter_id) +); + +create trigger + update_time_column +before +update on db_test_scooter_accessory + for each row execute procedure update_time_column(); + +create trigger + immutable_columns +before +update on db_test_scooter_accessory + for each row execute procedure immutable_columns('create_time'); + +create trigger + default_create_time_column +before +insert on db_test_scooter_accessory + for each row execute procedure default_create_time(); + +commit; +` + testQueryDropTables = ` +begin; +drop table if exists db_test_user cascade; +drop table if exists db_test_car cascade; +drop table if exists db_test_rental cascade; +drop table if exists db_test_scooter cascade; +drop table if exists db_test_accessory cascade; +drop table if exists db_test_scooter_accessory cascade; +commit; +` + + testQueryAddOplogEntries = ` +begin; + +insert into oplog_ticket (name, version) +values + ('db_test_user', 1), + ('db_test_car', 1), + ('db_test_rental', 1), + ('db_test_scooter', 1), + ('db_test_accessory', 1), + ('db_test_scooter_accessory', 1); +commit; +` + testQueryDeleteOplogEntries = ` +begin; + +delete from oplog_ticket where name in +( + 'db_test_user', + 'db_test_car', + 'db_test_rental', + 'db_test_scooter', + 'db_test_accessory', + 'db_test_scooter_accessory' +); + +commit; +` +) diff --git a/internal/db/testing_test.go b/internal/db/testing_test.go index 75e0b4e89..bffe0b3a9 100644 --- a/internal/db/testing_test.go +++ b/internal/db/testing_test.go @@ -23,6 +23,7 @@ func Test_Utils(t *testing.T) { func TestVerifyOplogEntry(t *testing.T) { db, _ := TestSetup(t, "postgres") assert := assert.New(t) + TestCreateTables(t, db) t.Run("valid", func(t *testing.T) { rw := Db{underlying: db} diff --git a/internal/oplog/testing_test.go b/internal/oplog/testing_test.go index 93436e7c1..3478813b6 100644 --- a/internal/oplog/testing_test.go +++ b/internal/oplog/testing_test.go @@ -75,7 +75,7 @@ func Test_testInitStore(t *testing.T) { testInitStore(t, cleanup, url) const query = ` -select count(*) from information_schema."tables" t where table_name = 'db_test_user'; +select count(*) from information_schema."tables" t where table_name = 'boundary_schema_version'; ` db, err := common.SqlOpen("postgres", url) require.NoError(err)