github.com/scraniel/migrate@v0.0.0-20230320185700-339088f36cee/database/firebird/firebird_test.go (about) 1 package firebird 2 3 import ( 4 "context" 5 "database/sql" 6 sqldriver "database/sql/driver" 7 "fmt" 8 "log" 9 10 "github.com/golang-migrate/migrate/v4" 11 "io" 12 "strings" 13 "testing" 14 15 "github.com/dhui/dktest" 16 17 dt "github.com/golang-migrate/migrate/v4/database/testing" 18 "github.com/golang-migrate/migrate/v4/dktesting" 19 _ "github.com/golang-migrate/migrate/v4/source/file" 20 21 _ "github.com/nakagami/firebirdsql" 22 ) 23 24 const ( 25 user = "test_user" 26 password = "123456" 27 dbName = "test.fdb" 28 ) 29 30 var ( 31 opts = dktest.Options{ 32 PortRequired: true, 33 ReadyFunc: isReady, 34 Env: map[string]string{ 35 "FIREBIRD_DATABASE": dbName, 36 "FIREBIRD_USER": user, 37 "FIREBIRD_PASSWORD": password, 38 }, 39 } 40 specs = []dktesting.ContainerSpec{ 41 {ImageName: "jacobalberty/firebird:2.5-ss", Options: opts}, 42 {ImageName: "jacobalberty/firebird:3.0", Options: opts}, 43 } 44 ) 45 46 func fbConnectionString(host, port string) string { 47 //firebird://user:password@servername[:port_number]/database_name_or_file[?params1=value1[¶m2=value2]...] 48 return fmt.Sprintf("firebird://%s:%s@%s:%s//firebird/data/%s", user, password, host, port, dbName) 49 } 50 51 func isReady(ctx context.Context, c dktest.ContainerInfo) bool { 52 ip, port, err := c.FirstPort() 53 if err != nil { 54 return false 55 } 56 57 db, err := sql.Open("firebirdsql", fbConnectionString(ip, port)) 58 if err != nil { 59 log.Println("open error:", err) 60 return false 61 } 62 defer func() { 63 if err := db.Close(); err != nil { 64 log.Println("close error:", err) 65 } 66 }() 67 if err = db.PingContext(ctx); err != nil { 68 switch err { 69 case sqldriver.ErrBadConn, io.EOF: 70 return false 71 default: 72 log.Println(err) 73 } 74 return false 75 } 76 77 return true 78 } 79 80 func Test(t *testing.T) { 81 dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { 82 ip, port, err := c.FirstPort() 83 if err != nil { 84 t.Fatal(err) 85 } 86 87 addr := fbConnectionString(ip, port) 88 p := &Firebird{} 89 d, err := p.Open(addr) 90 if err != nil { 91 t.Fatal(err) 92 } 93 defer func() { 94 if err := d.Close(); err != nil { 95 t.Error(err) 96 } 97 }() 98 dt.Test(t, d, []byte("SELECT Count(*) FROM rdb$relations")) 99 }) 100 } 101 102 func TestMigrate(t *testing.T) { 103 dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { 104 ip, port, err := c.FirstPort() 105 if err != nil { 106 t.Fatal(err) 107 } 108 109 addr := fbConnectionString(ip, port) 110 p := &Firebird{} 111 d, err := p.Open(addr) 112 if err != nil { 113 t.Fatal(err) 114 } 115 defer func() { 116 if err := d.Close(); err != nil { 117 t.Error(err) 118 } 119 }() 120 m, err := migrate.NewWithDatabaseInstance("file://./examples/migrations", "firebirdsql", d) 121 if err != nil { 122 t.Fatal(err) 123 } 124 dt.TestMigrate(t, m) 125 }) 126 } 127 128 func TestErrorParsing(t *testing.T) { 129 dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { 130 ip, port, err := c.FirstPort() 131 if err != nil { 132 t.Fatal(err) 133 } 134 135 addr := fbConnectionString(ip, port) 136 p := &Firebird{} 137 d, err := p.Open(addr) 138 if err != nil { 139 t.Fatal(err) 140 } 141 defer func() { 142 if err := d.Close(); err != nil { 143 t.Error(err) 144 } 145 }() 146 147 wantErr := `migration failed in line 0: CREATE TABLEE foo (foo varchar(40)); (details: Dynamic SQL Error 148 SQL error code = -104 149 Token unknown - line 1, column 8 150 TABLEE 151 )` 152 153 if err := d.Run(strings.NewReader("CREATE TABLEE foo (foo varchar(40));")); err == nil { 154 t.Fatal("expected err but got nil") 155 } else if err.Error() != wantErr { 156 msg := err.Error() 157 t.Fatalf("expected '%s' but got '%s'", wantErr, msg) 158 } 159 }) 160 } 161 162 func TestFilterCustomQuery(t *testing.T) { 163 dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { 164 ip, port, err := c.FirstPort() 165 if err != nil { 166 t.Fatal(err) 167 } 168 169 addr := fbConnectionString(ip, port) + "?sslmode=disable&x-custom=foobar" 170 p := &Firebird{} 171 d, err := p.Open(addr) 172 if err != nil { 173 t.Fatal(err) 174 } 175 defer func() { 176 if err := d.Close(); err != nil { 177 t.Error(err) 178 } 179 }() 180 }) 181 } 182 183 func Test_Lock(t *testing.T) { 184 dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) { 185 ip, port, err := c.FirstPort() 186 if err != nil { 187 t.Fatal(err) 188 } 189 190 addr := fbConnectionString(ip, port) 191 p := &Firebird{} 192 d, err := p.Open(addr) 193 if err != nil { 194 t.Fatal(err) 195 } 196 defer func() { 197 if err := d.Close(); err != nil { 198 t.Error(err) 199 } 200 }() 201 202 dt.Test(t, d, []byte("SELECT Count(*) FROM rdb$relations")) 203 204 ps := d.(*Firebird) 205 206 err = ps.Lock() 207 if err != nil { 208 t.Fatal(err) 209 } 210 211 err = ps.Unlock() 212 if err != nil { 213 t.Fatal(err) 214 } 215 216 err = ps.Lock() 217 if err != nil { 218 t.Fatal(err) 219 } 220 221 err = ps.Unlock() 222 if err != nil { 223 t.Fatal(err) 224 } 225 }) 226 }