gitlab.com/beacon-software/gadget@v0.0.0-20181217202115-54565ea1ed5e/database/setup_test.go (about) 1 package database 2 3 import ( 4 "database/sql" 5 "fmt" 6 "os" 7 "testing" 8 "time" 9 10 "github.com/mattes/migrate" 11 12 "gitlab.com/beacon-software/gadget/database/qb" 13 "gitlab.com/beacon-software/gadget/environment" 14 "gitlab.com/beacon-software/gadget/generator" 15 "gitlab.com/beacon-software/gadget/log" 16 ) 17 18 type specification struct { 19 DatabaseType string 20 DatabaseURL string `env:"TST_DATABASE_URL"` 21 DB *Database 22 } 23 24 // DatabaseConnection return the connection string for the database 25 func (spec specification) DatabaseConnection() string { 26 return spec.DatabaseURL 27 } 28 29 // DatabaseDialect returns the dialect (mysql, mongo, etc) for the connection 30 func (spec specification) DatabaseDialect() string { 31 return spec.DatabaseType 32 } 33 34 // DatabaseDialectURL returns the dialect (mysql, mongo, etc) for the connection 35 func (spec specification) DatabaseDialectURL() string { 36 return fmt.Sprintf("%s://%s", spec.DatabaseType, spec.DatabaseURL) 37 } 38 39 func newSpecification() *specification { 40 config := &specification{ 41 DatabaseType: "mysql", 42 } 43 environment.Process(config) 44 config.DB = Initialize(config) 45 return config 46 } 47 48 // testMeta defines a table 49 type testMeta struct { 50 alias string 51 ID qb.TableField 52 Name qb.TableField 53 Place qb.TableField 54 55 CreatedOn qb.TableField 56 UpdatedOn qb.TableField 57 } 58 59 func (p *testMeta) GetName() string { 60 return "test_record" 61 } 62 63 func (p *testMeta) GetAlias() string { 64 return p.alias 65 } 66 67 func (p *testMeta) PrimaryKey() qb.TableField { 68 return p.ID 69 } 70 71 func (p *testMeta) AllColumns() qb.TableField { 72 return qb.TableField{Table: p.GetName(), Name: "*"} 73 } 74 75 func (p *testMeta) SortBy() (qb.TableField, qb.OrderDirection) { 76 return p.CreatedOn, qb.Ascending 77 } 78 79 func (p *testMeta) ReadColumns() []qb.TableField { 80 return []qb.TableField{ 81 p.ID, 82 p.Name, 83 p.Place, 84 p.CreatedOn, 85 p.UpdatedOn, 86 } 87 } 88 89 func (p *testMeta) WriteColumns() []qb.TableField { 90 return []qb.TableField{ 91 p.Name, 92 p.Place, 93 } 94 } 95 96 func (p *testMeta) Alias(alias string) *testMeta { 97 return &testMeta{ 98 alias: alias, 99 ID: qb.TableField{Name: "id", Table: alias}, 100 Name: qb.TableField{Name: "name", Table: alias}, 101 Place: qb.TableField{Name: "place", Table: alias}, 102 103 CreatedOn: qb.TableField{Name: "created_on", Table: alias}, 104 UpdatedOn: qb.TableField{Name: "updated_on", Table: alias}, 105 } 106 } 107 108 var TestMeta = (&testMeta{}).Alias("test_record") 109 110 type TestRecord struct { 111 DefaultRecord 112 ID string `db:"id,read_only"` 113 Name string `db:"name"` 114 Place sql.NullString `db:"place"` 115 CreatedOn time.Time `db:"created_on,read_only"` 116 UpdatedOn time.Time `db:"updated_on,read_only"` 117 Skip string 118 } 119 120 func (record *TestRecord) Initialize() { 121 record.ID = generator.ID("tst") 122 } 123 124 func (record *TestRecord) PrimaryKey() PrimaryKeyValue { 125 return NewPrimaryKey(record.ID) 126 } 127 128 func (record *TestRecord) Meta() qb.Table { 129 return TestMeta 130 } 131 132 // detailsTestMeta defines a table 133 type detailsTestMeta struct { 134 alias string 135 ID qb.TableField 136 Name qb.TableField 137 } 138 139 func (p *detailsTestMeta) GetName() string { 140 return "details_test_record" 141 } 142 143 func (p *detailsTestMeta) GetAlias() string { 144 return p.alias 145 } 146 147 func (p *detailsTestMeta) PrimaryKey() qb.TableField { 148 return p.ID 149 } 150 151 func (p *detailsTestMeta) AllColumns() qb.TableField { 152 return qb.TableField{Table: p.GetName(), Name: "*"} 153 } 154 155 func (p *detailsTestMeta) SortBy() (qb.TableField, qb.OrderDirection) { 156 return p.ID, qb.Ascending 157 } 158 159 func (p *detailsTestMeta) ReadColumns() []qb.TableField { 160 return p.WriteColumns() 161 } 162 163 func (p *detailsTestMeta) WriteColumns() []qb.TableField { 164 return []qb.TableField{ 165 p.ID, 166 p.Name, 167 } 168 } 169 170 func (p *detailsTestMeta) Alias(alias string) *detailsTestMeta { 171 return &detailsTestMeta{ 172 alias: alias, 173 ID: qb.TableField{Name: "id", Table: alias}, 174 Name: qb.TableField{Name: "name", Table: alias}, 175 } 176 } 177 178 var DetailsTestMeta = (&detailsTestMeta{}).Alias("details_test_record") 179 180 type DetailsTestRecord struct { 181 ID string `db:"id,nonsense"` 182 Name string `db:"name"` 183 } 184 185 func (record DetailsTestRecord) Meta() qb.Table { 186 return DetailsTestMeta 187 } 188 189 func (record DetailsTestRecord) Initialize() { 190 } 191 192 func (record DetailsTestRecord) Key() string { 193 return "name" 194 } 195 196 func (record DetailsTestRecord) PrimaryKey() PrimaryKeyValue { 197 return NewPrimaryKey(record.ID) 198 } 199 200 // testDuperMeta defines a table 201 type testDuperMeta struct { 202 alias string 203 ID qb.TableField 204 } 205 206 func (p *testDuperMeta) GetName() string { 207 return "test_duper" 208 } 209 210 func (p *testDuperMeta) GetAlias() string { 211 return p.alias 212 } 213 214 func (p *testDuperMeta) PrimaryKey() qb.TableField { 215 return p.ID 216 } 217 218 func (p *testDuperMeta) AllColumns() qb.TableField { 219 return qb.TableField{Table: p.GetName(), Name: "*"} 220 } 221 222 func (p *testDuperMeta) SortBy() (qb.TableField, qb.OrderDirection) { 223 return p.ID, qb.Ascending 224 } 225 226 func (p *testDuperMeta) ReadColumns() []qb.TableField { 227 return p.WriteColumns() 228 } 229 230 func (p *testDuperMeta) WriteColumns() []qb.TableField { 231 return []qb.TableField{p.ID} 232 } 233 234 func (p *testDuperMeta) Alias(alias string) *testDuperMeta { 235 return &testDuperMeta{ 236 alias: alias, 237 ID: qb.TableField{Name: "id", Table: alias}, 238 } 239 } 240 241 var TestDuperMeta = (&testDuperMeta{}).Alias("test_duper") 242 243 type TestDuper struct { 244 ID string `db:"id"` 245 intializer func() string 246 } 247 248 func (record *TestDuper) Meta() qb.Table { 249 return TestDuperMeta 250 } 251 252 func (record *TestDuper) Initialize() { 253 log.Debugf("\n\nInitializing: %s", record.ID) 254 record.ID = record.intializer() 255 log.Debugf("Initialized: %s\n\n", record.ID) 256 257 } 258 259 func (record *TestDuper) Key() string { 260 return "id" 261 } 262 263 func (record *TestDuper) PrimaryKey() PrimaryKeyValue { 264 return NewPrimaryKey(record.ID) 265 } 266 267 func initialize() string { 268 return generator.ID("dup") 269 } 270 271 func NewTestDuper() *TestDuper { 272 return &TestDuper{ 273 intializer: initialize, 274 } 275 } 276 277 func rollback(migrations map[string]string, dbURL string) { 278 sqlFilesPath, _ := generateSQLFiles(migrations) 279 m, err := migrate.New(sqlFilesPath, dbURL) 280 if err != nil { 281 msg := fmt.Sprintf("couldn't load migration scripts from %s (%s)", sqlFilesPath, err) 282 log.Fatalf(msg) 283 panic(msg) 284 } 285 defer m.Close() 286 287 // Migrate all the way down ... 288 if err := m.Down(); err != nil { 289 msg := fmt.Sprintf("Rollback ERROR: %#v", err) 290 log.Fatalf(msg) 291 panic(msg) 292 } 293 } 294 295 func TestMain(m *testing.M) { 296 config := newSpecification() 297 migrations := make(map[string]string) 298 migrations["0001_.up.sql"] = `CREATE TABLE IF NOT EXISTS test_record ( 299 id varchar(128) primary key, 300 name varchar(128) not null unique, 301 place varchar(128) null, 302 created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 303 updated_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 304 ); 305 CREATE TABLE IF NOT EXISTS test_duper ( 306 id varchar(128) primary key 307 ); 308 ` 309 migrations["0001_foo.down.sql"] = `DROP TABLE IF EXISTS test_record; 310 DROP TABLE IF EXISTS test_duper; 311 ` 312 Migrate(migrations, config.DatabaseDialectURL()) 313 314 res := m.Run() 315 Reset(migrations, config.DatabaseDialectURL()) 316 317 os.Exit(res) 318 }