Skip to content

Commit c7ca877

Browse files
committed
More tests.
1 parent 663aa59 commit c7ca877

2 files changed

Lines changed: 259 additions & 11 deletions

File tree

dialects_test.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package dmorph
22

33
import (
4-
"github.com/stretchr/testify/assert"
4+
"database/sql"
5+
"os"
56
"testing"
7+
8+
"github.com/stretchr/testify/assert"
69
)
710

811
func TestDialectStatements(t *testing.T) {
@@ -42,3 +45,56 @@ func TestDialectStatements(t *testing.T) {
4245
"no table name placeholder in register template for", v.name)
4346
}
4447
}
48+
49+
func TestCallsOnClosedDB(t *testing.T) {
50+
dbFile, dbFileErr := prepareDB()
51+
52+
if dbFileErr != nil {
53+
t.Errorf("DB file could not be created: %v", dbFileErr)
54+
} else {
55+
defer func() { _ = os.Remove(dbFile) }()
56+
}
57+
58+
db, dbErr := sql.Open("sqlite", dbFile)
59+
60+
if dbErr != nil {
61+
t.Errorf("DB file could not be created: %v", dbErr)
62+
} else {
63+
_ = db.Close()
64+
}
65+
66+
assert.Error(t,
67+
DialectSQLite().EnsureMigrationTableExists(db, "irrelevant"),
68+
"expected error on closed database")
69+
70+
_, err := DialectSQLite().AppliedMigrations(db, "irrelevant")
71+
assert.Error(t, err, "expected error on closed database")
72+
}
73+
74+
func TestEnsureMigrationTableExistsSQLError(t *testing.T) {
75+
d := BaseDialect{
76+
CreateTemplate: `
77+
CRATE TABLE test (
78+
id VARCHAR(255) PRIMARY KEY,
79+
create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
80+
)`,
81+
}
82+
83+
dbFile, dbFileErr := prepareDB()
84+
85+
if dbFileErr != nil {
86+
t.Errorf("DB file could not be created: %v", dbFileErr)
87+
} else {
88+
defer func() { _ = os.Remove(dbFile) }()
89+
}
90+
91+
db, dbErr := sql.Open("sqlite", dbFile)
92+
93+
if dbErr != nil {
94+
t.Errorf("DB file could not be created: %v", dbErr)
95+
} else {
96+
defer func() { _ = db.Close() }()
97+
}
98+
99+
assert.Error(t, d.EnsureMigrationTableExists(db, "test"), "expected error")
100+
}

migration_test.go

Lines changed: 202 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,42 @@ func TestMigration(t *testing.T) {
5959
WithDialect(DialectSQLite()),
6060
WithMigrationsFromFS(migrationsDir.(fs.ReadDirFS)))
6161

62-
if runErr != nil {
63-
t.Errorf("Migrations could not be run: %v", runErr)
62+
assert.NoError(t, runErr, "migrations could not be run")
63+
}
64+
65+
// TestMigrationUpdate tests the happy flow of updating on existing migrations.
66+
func TestMigrationUpdate(t *testing.T) {
67+
dbFile, dbFileErr := prepareDB()
68+
69+
if dbFileErr != nil {
70+
t.Errorf("DB file could not be created: %v", dbFileErr)
71+
} else {
72+
defer func() { _ = os.Remove(dbFile) }()
6473
}
74+
75+
db, dbErr := sql.Open("sqlite", dbFile)
76+
77+
if dbErr != nil {
78+
t.Errorf("DB file could not be created: %v", dbErr)
79+
} else {
80+
defer func() { _ = db.Close() }()
81+
}
82+
83+
migrationsDir, migrationsDirErr := fs.Sub(testMigrationsDir, "testData")
84+
85+
assert.NoError(t, migrationsDirErr, "migrations directory could not be opened")
86+
87+
runErr := Run(db,
88+
WithDialect(DialectSQLite()),
89+
WithMigrationFromFileFS("01_base_table.sql", migrationsDir))
90+
91+
assert.NoError(t, runErr, "preparation migrations could not be run")
92+
93+
runErr = Run(db,
94+
WithDialect(DialectSQLite()),
95+
WithMigrationsFromFS(migrationsDir.(fs.ReadDirFS)))
96+
97+
assert.NoError(t, runErr, "migrations could not be run")
6598
}
6699

67100
// TestMigration tests what happens, if the applied migrations are too old.
@@ -90,9 +123,7 @@ func TestMigrationTooOld(t *testing.T) {
90123
WithDialect(DialectSQLite()),
91124
WithMigrationsFromFS(migrationsDir.(fs.ReadDirFS)))
92125

93-
if runErr != nil {
94-
t.Errorf("preparation migrations could not be run: %v", runErr)
95-
}
126+
assert.NoError(t, runErr, "preparation migrations could not be run")
96127

97128
runErr = Run(db,
98129
WithDialect(DialectSQLite()),
@@ -101,8 +132,8 @@ func TestMigrationTooOld(t *testing.T) {
101132
assert.ErrorIs(t, runErr, ErrMigrationsTooOld, "migrations did not give expected error")
102133
}
103134

104-
// TestMigration tests what happens, if the applied migrations are unrelated to existing ones.
105-
func TestMigrationUnrelated(t *testing.T) {
135+
// TestMigrationUnrelated0 tests what happens, if the applied migrations are unrelated to existing ones.
136+
func TestMigrationUnrelated0(t *testing.T) {
106137
dbFile, dbFileErr := prepareDB()
107138

108139
if dbFileErr != nil {
@@ -125,15 +156,176 @@ func TestMigrationUnrelated(t *testing.T) {
125156

126157
runErr := Run(db,
127158
WithDialect(DialectSQLite()),
128-
WithMigrationFromFileFS("01_base_table.sql", migrationsDir))
159+
WithMigrationsFromFS(migrationsDir.(fs.ReadDirFS)))
160+
161+
assert.NoError(t, runErr, "preparation migrations could not be run")
162+
163+
runErr = Run(db,
164+
WithDialect(DialectSQLite()),
165+
WithMigrationFromFileFS("02_addon_table.sql", migrationsDir))
166+
167+
assert.ErrorIs(t, runErr, ErrMigrationsUnrelated, "migrations did not give expected error")
168+
}
169+
170+
// TestMigrationUnrelated1 tests what happens, if the applied migrations are unrelated to existing ones.
171+
func TestMigrationUnrelated1(t *testing.T) {
172+
dbFile, dbFileErr := prepareDB()
129173

130-
if runErr != nil {
131-
t.Errorf("preparation migrations could not be run: %v", runErr)
174+
if dbFileErr != nil {
175+
t.Errorf("DB file could not be created: %v", dbFileErr)
176+
} else {
177+
defer func() { _ = os.Remove(dbFile) }()
132178
}
133179

180+
db, dbErr := sql.Open("sqlite", dbFile)
181+
182+
if dbErr != nil {
183+
t.Errorf("DB file could not be created: %v", dbErr)
184+
} else {
185+
defer func() { _ = db.Close() }()
186+
}
187+
188+
migrationsDir, migrationsDirErr := fs.Sub(testMigrationsDir, "testData")
189+
190+
assert.NoError(t, migrationsDirErr, "migrations directory could not be opened")
191+
192+
runErr := Run(db,
193+
WithDialect(DialectSQLite()),
194+
WithMigrationFromFileFS("01_base_table.sql", migrationsDir))
195+
196+
assert.NoError(t, runErr, "preparation migrations could not be run")
197+
134198
runErr = Run(db,
135199
WithDialect(DialectSQLite()),
136200
WithMigrationFromFileFS("02_addon_table.sql", migrationsDir))
137201

138202
assert.ErrorIs(t, runErr, ErrMigrationsUnrelated, "migrations did not give expected error")
139203
}
204+
205+
// TestMigrationAppliedUnordered tests the case, that somehow the migrations in the
206+
// database are registered not in the order of their keys.
207+
func TestMigrationAppliedUnordered(t *testing.T) {
208+
dbFile, dbFileErr := prepareDB()
209+
210+
if dbFileErr != nil {
211+
t.Errorf("DB file could not be created: %v", dbFileErr)
212+
} else {
213+
defer func() { _ = os.Remove(dbFile) }()
214+
}
215+
216+
db, dbErr := sql.Open("sqlite", dbFile)
217+
218+
if dbErr != nil {
219+
t.Errorf("DB file could not be created: %v", dbErr)
220+
} else {
221+
defer func() { _ = db.Close() }()
222+
}
223+
224+
migrationsDir, migrationsDirErr := fs.Sub(testMigrationsDir, "testData")
225+
226+
assert.NoError(t, migrationsDirErr, "migrations directory could not be opened")
227+
228+
assert.NoError(t, DialectSQLite().EnsureMigrationTableExists(db, "migrations"))
229+
230+
_, execErr := db.Exec(`
231+
INSERT INTO migrations (id, create_ts) VALUES ('01_base_table', '2021-01-02 00:00:00');
232+
INSERT INTO migrations (id, create_ts) VALUES ('02_addon_table', '2021-01-01 00:00:00');
233+
`)
234+
235+
assert.NoError(t, execErr, "unordered test could not be prepared")
236+
237+
runErr := Run(db,
238+
WithDialect(DialectSQLite()),
239+
WithMigrationsFromFS(migrationsDir.(fs.ReadDirFS)))
240+
241+
assert.ErrorIs(t,
242+
runErr,
243+
ErrMigrationsUnsorted,
244+
"migrations did not give expected error")
245+
}
246+
247+
// TestMigrationOrder checks that the migrations ordering function works as expected.
248+
func TestMigrationOrder(t *testing.T) {
249+
tests := []struct {
250+
m0 Migration
251+
m1 Migration
252+
order int
253+
}{
254+
{
255+
m0: FileMigration{Name: "01"},
256+
m1: FileMigration{Name: "01"},
257+
order: 0,
258+
},
259+
{
260+
m0: FileMigration{Name: "01"},
261+
m1: FileMigration{Name: "02"},
262+
order: -1,
263+
},
264+
{
265+
m0: FileMigration{Name: "02"},
266+
m1: FileMigration{Name: "01"},
267+
order: 1,
268+
},
269+
}
270+
271+
for k, v := range tests {
272+
res := migrationOrder(v.m0, v.m1)
273+
274+
assert.Equal(t, v.order, res, "order of migrations is wrong for test %v", k)
275+
}
276+
}
277+
278+
// TestMigrationIsValid checks the validity checks for migrations.
279+
func TestMigrationIsValid(t *testing.T) {
280+
tests := []struct {
281+
m Morpher
282+
err error
283+
}{
284+
{
285+
m: Morpher{
286+
Dialect: DialectSQLite(),
287+
Migrations: []Migration{FileMigration{Name: "01"}},
288+
TableName: "migrations",
289+
},
290+
err: nil,
291+
},
292+
{
293+
m: Morpher{
294+
Dialect: nil,
295+
Migrations: []Migration{FileMigration{Name: "01"}},
296+
TableName: "migrations",
297+
},
298+
err: ErrNoDialect,
299+
},
300+
{
301+
m: Morpher{
302+
Dialect: DialectSQLite(),
303+
Migrations: nil,
304+
TableName: "migrations",
305+
},
306+
err: ErrNoMigrations,
307+
},
308+
{
309+
m: Morpher{
310+
Dialect: DialectSQLite(),
311+
Migrations: []Migration{FileMigration{Name: "01"}},
312+
TableName: "",
313+
},
314+
err: ErrNoMigrationTable,
315+
},
316+
{
317+
m: Morpher{
318+
Dialect: DialectSQLite(),
319+
Migrations: []Migration{FileMigration{Name: "01"}},
320+
TableName: "blah(); DROP TABLE blah;",
321+
},
322+
err: ErrMigrationTableNameInvalid,
323+
},
324+
}
325+
326+
for k, v := range tests {
327+
err := v.m.IsValid()
328+
329+
assert.ErrorIs(t, err, v.err, "error is wrong for test %v", k)
330+
}
331+
}

0 commit comments

Comments
 (0)