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 }