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[&param2=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  }