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