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 }