@@ -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