github.com/scraniel/migrate@v0.0.0-20230320185700-339088f36cee/database/clickhouse/clickhouse_test.go (about)

     1  package clickhouse_test
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	sqldriver "database/sql/driver"
     7  	"fmt"
     8  	"log"
     9  	"testing"
    10  
    11  	_ "github.com/ClickHouse/clickhouse-go"
    12  	"github.com/dhui/dktest"
    13  	"github.com/golang-migrate/migrate/v4"
    14  	"github.com/golang-migrate/migrate/v4/database/clickhouse"
    15  	dt "github.com/golang-migrate/migrate/v4/database/testing"
    16  	"github.com/golang-migrate/migrate/v4/dktesting"
    17  	_ "github.com/golang-migrate/migrate/v4/source/file"
    18  )
    19  
    20  const defaultPort = 9000
    21  
    22  var (
    23  	tableEngines = []string{"TinyLog", "MergeTree"}
    24  	opts         = dktest.Options{
    25  		Env:          map[string]string{"CLICKHOUSE_USER": "user", "CLICKHOUSE_PASSWORD": "password", "CLICKHOUSE_DB": "db"},
    26  		PortRequired: true, ReadyFunc: isReady,
    27  	}
    28  	specs = []dktesting.ContainerSpec{
    29  		{ImageName: "yandex/clickhouse-server:21.3", Options: opts},
    30  	}
    31  )
    32  
    33  func clickhouseConnectionString(host, port, engine string) string {
    34  	if engine != "" {
    35  		return fmt.Sprintf(
    36  			"clickhouse://%v:%v?username=user&password=password&database=db&x-multi-statement=true&x-migrations-table-engine=%v&debug=false",
    37  			host, port, engine)
    38  	}
    39  
    40  	return fmt.Sprintf(
    41  		"clickhouse://%v:%v?username=user&password=password&database=db&x-multi-statement=true&debug=false",
    42  		host, port)
    43  }
    44  
    45  func isReady(ctx context.Context, c dktest.ContainerInfo) bool {
    46  	ip, port, err := c.Port(defaultPort)
    47  	if err != nil {
    48  		return false
    49  	}
    50  
    51  	db, err := sql.Open("clickhouse", clickhouseConnectionString(ip, port, ""))
    52  
    53  	if err != nil {
    54  		log.Println("open error", err)
    55  		return false
    56  	}
    57  	defer func() {
    58  		if err := db.Close(); err != nil {
    59  			log.Println("close error:", err)
    60  		}
    61  	}()
    62  
    63  	if err = db.PingContext(ctx); err != nil {
    64  		switch err {
    65  		case sqldriver.ErrBadConn:
    66  			return false
    67  		default:
    68  			fmt.Println(err)
    69  		}
    70  		return false
    71  	}
    72  
    73  	return true
    74  }
    75  
    76  func TestCases(t *testing.T) {
    77  	for _, engine := range tableEngines {
    78  		t.Run("Test_"+engine, func(t *testing.T) { testSimple(t, engine) })
    79  		t.Run("Migrate_"+engine, func(t *testing.T) { testMigrate(t, engine) })
    80  		t.Run("Version_"+engine, func(t *testing.T) { testVersion(t, engine) })
    81  		t.Run("Drop_"+engine, func(t *testing.T) { testDrop(t, engine) })
    82  	}
    83  	t.Run("WithInstanceDefaultConfigValues", func(t *testing.T) { testSimpleWithInstanceDefaultConfigValues(t) })
    84  }
    85  
    86  func testSimple(t *testing.T, engine string) {
    87  	dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) {
    88  		ip, port, err := c.Port(defaultPort)
    89  		if err != nil {
    90  			t.Fatal(err)
    91  		}
    92  
    93  		addr := clickhouseConnectionString(ip, port, engine)
    94  		p := &clickhouse.ClickHouse{}
    95  		d, err := p.Open(addr)
    96  		if err != nil {
    97  			t.Fatal(err)
    98  		}
    99  		defer func() {
   100  			if err := d.Close(); err != nil {
   101  				t.Error(err)
   102  			}
   103  		}()
   104  
   105  		dt.Test(t, d, []byte("SELECT 1"))
   106  	})
   107  }
   108  
   109  func testSimpleWithInstanceDefaultConfigValues(t *testing.T) {
   110  	dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) {
   111  		ip, port, err := c.Port(defaultPort)
   112  		if err != nil {
   113  			t.Fatal(err)
   114  		}
   115  
   116  		addr := clickhouseConnectionString(ip, port, "")
   117  		conn, err := sql.Open("clickhouse", addr)
   118  		if err != nil {
   119  			t.Fatal(err)
   120  		}
   121  		d, err := clickhouse.WithInstance(conn, &clickhouse.Config{})
   122  		if err != nil {
   123  			_ = conn.Close()
   124  			t.Fatal(err)
   125  		}
   126  		defer func() {
   127  			if err := d.Close(); err != nil {
   128  				t.Error(err)
   129  			}
   130  		}()
   131  
   132  		dt.Test(t, d, []byte("SELECT 1"))
   133  	})
   134  }
   135  
   136  func testMigrate(t *testing.T, engine string) {
   137  	dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) {
   138  		ip, port, err := c.Port(defaultPort)
   139  		if err != nil {
   140  			t.Fatal(err)
   141  		}
   142  
   143  		addr := clickhouseConnectionString(ip, port, engine)
   144  		p := &clickhouse.ClickHouse{}
   145  		d, err := p.Open(addr)
   146  		if err != nil {
   147  			t.Fatal(err)
   148  		}
   149  		defer func() {
   150  			if err := d.Close(); err != nil {
   151  				t.Error(err)
   152  			}
   153  		}()
   154  		m, err := migrate.NewWithDatabaseInstance("file://./examples/migrations", "db", d)
   155  
   156  		if err != nil {
   157  			t.Fatal(err)
   158  		}
   159  		dt.TestMigrate(t, m)
   160  	})
   161  }
   162  
   163  func testVersion(t *testing.T, engine string) {
   164  	dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) {
   165  		expectedVersion := 1
   166  
   167  		ip, port, err := c.Port(defaultPort)
   168  		if err != nil {
   169  			t.Fatal(err)
   170  		}
   171  
   172  		addr := clickhouseConnectionString(ip, port, engine)
   173  		p := &clickhouse.ClickHouse{}
   174  		d, err := p.Open(addr)
   175  		if err != nil {
   176  			t.Fatal(err)
   177  		}
   178  		defer func() {
   179  			if err := d.Close(); err != nil {
   180  				t.Error(err)
   181  			}
   182  		}()
   183  
   184  		err = d.SetVersion(expectedVersion, false)
   185  		if err != nil {
   186  			t.Fatal(err)
   187  		}
   188  
   189  		version, _, err := d.Version()
   190  		if err != nil {
   191  			t.Fatal(err)
   192  		}
   193  
   194  		if version != expectedVersion {
   195  			t.Fatal("Version mismatch")
   196  		}
   197  	})
   198  }
   199  
   200  func testDrop(t *testing.T, engine string) {
   201  	dktesting.ParallelTest(t, specs, func(t *testing.T, c dktest.ContainerInfo) {
   202  		ip, port, err := c.Port(defaultPort)
   203  		if err != nil {
   204  			t.Fatal(err)
   205  		}
   206  
   207  		addr := clickhouseConnectionString(ip, port, engine)
   208  		p := &clickhouse.ClickHouse{}
   209  		d, err := p.Open(addr)
   210  		if err != nil {
   211  			t.Fatal(err)
   212  		}
   213  		defer func() {
   214  			if err := d.Close(); err != nil {
   215  				t.Error(err)
   216  			}
   217  		}()
   218  
   219  		err = d.Drop()
   220  		if err != nil {
   221  			t.Fatal(err)
   222  		}
   223  	})
   224  }