package db import ( "reflect" "testing" ) func TestClickHouseOptionsHostPort(t *testing.T) { opts, err := ClickHouseOptions("localhost:9000") if err != nil { t.Fatalf("ClickHouseOptions: %v", err) } if len(opts.Addr) != 1 || opts.Addr[0] != "localhost:9000" { t.Fatalf("Addr=%v want [localhost:9000]", opts.Addr) } if opts.Auth.Username != "" || opts.Auth.Password != "" || opts.Auth.Database != "" { t.Fatalf("Auth=%+v want empty", opts.Auth) } } func TestClickHouseOptionsURLWithAuthAndDatabase(t *testing.T) { opts, err := ClickHouseOptions("clickhouse://user%40name:p%2Fass@localhost:9000/token%20thief?compress=zstd") if err != nil { t.Fatalf("ClickHouseOptions: %v", err) } if len(opts.Addr) != 1 || opts.Addr[0] != "localhost:9000" { t.Fatalf("Addr=%v want [localhost:9000]", opts.Addr) } if opts.Auth.Username != "user@name" { t.Fatalf("Username=%q want user@name", opts.Auth.Username) } if opts.Auth.Password != "p/ass" { t.Fatalf("Password=%q want p/ass", opts.Auth.Password) } if opts.Auth.Database != "token thief" { t.Fatalf("Database=%q want token thief", opts.Auth.Database) } if opts.Compression == nil { t.Fatal("Compression=nil want enabled") } } func TestClickHouseOptionsURLWithDatabaseOnly(t *testing.T) { opts, err := ClickHouseOptions("clickhouse://localhost:9000/tokenthief") if err != nil { t.Fatalf("ClickHouseOptions: %v", err) } if len(opts.Addr) != 1 || opts.Addr[0] != "localhost:9000" { t.Fatalf("Addr=%v want [localhost:9000]", opts.Addr) } if opts.Auth.Database != "tokenthief" { t.Fatalf("Database=%q want tokenthief", opts.Auth.Database) } } func TestClickHouseOptionsTLS(t *testing.T) { opts, err := ClickHouseOptions("clickhouses://localhost:9440/tokenthief?skip_verify=true") if err != nil { t.Fatalf("ClickHouseOptions: %v", err) } if opts.TLS == nil || !opts.TLS.InsecureSkipVerify { t.Fatalf("TLS=%+v want InsecureSkipVerify", opts.TLS) } } func TestClickHouseOptionsRejectsInvalidDSN(t *testing.T) { tests := []string{ "localhost", "localhost:http", "clickhouse://localhost/tokenthief", "clickhouse:///tokenthief", "clickhouse://localhost:9000/db#fragment", "clickhouse://localhost:9000/db?unknown=true", "clickhouse://localhost:9000/db?compress=snappy", "clickhouse://localhost:9000/db?compress=lz4&compress=zstd", "clickhouse://localhost:9000/db?compress=%zz", "clickhouse://localhost:9000/db?secure=true", "clickhouses://localhost:9440/db?secure=false", "clickhouses://localhost:9440/db?skip_verify=maybe", "clickhouses://localhost:9440/db?skip_verify=", "clickhouse://localhost:9000/db?skip_verify=true", "https://localhost:9440/db", } for _, dsn := range tests { t.Run(dsn, func(t *testing.T) { if _, err := ClickHouseOptions(dsn); err == nil { t.Fatalf("ClickHouseOptions(%q) succeeded", dsn) } }) } } func TestValidateProxyLogsSchema(t *testing.T) { columns := append([]schemaColumn(nil), proxyLogsColumns...) table := schemaTable{ engine: "MergeTree", partitionKey: "toYYYYMM(started_at)", sortingKey: "started_at, request_id", } if err := validateProxyLogsSchema(columns, table); err != nil { t.Fatalf("validateProxyLogsSchema: %v", err) } badColumns := append([]schemaColumn(nil), columns...) badColumns[8].typ = "UInt16" tests := []struct { name string columns []schemaColumn table schemaTable }{ {"missing column", columns[:16], table}, {"wrong type", badColumns, table}, {"wrong engine", columns, schemaTable{"ReplacingMergeTree", table.partitionKey, table.sortingKey}}, {"wrong partition", columns, schemaTable{table.engine, "toDate(started_at)", table.sortingKey}}, {"wrong sorting", columns, schemaTable{table.engine, table.partitionKey, "request_id"}}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { if err := validateProxyLogsSchema(test.columns, test.table); err == nil { t.Fatal("validateProxyLogsSchema succeeded") } }) } if !reflect.DeepEqual(columns, proxyLogsColumns) { t.Fatal("schema validation mutated columns") } }