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