1package gosnowflake
2
3import (
4	"fmt"
5	"net/url"
6	"reflect"
7	"testing"
8	"time"
9)
10
11type tcParseDSN struct {
12	dsn      string
13	config   *Config
14	ocspMode string
15	err      error
16}
17
18func TestParseDSN(t *testing.T) {
19
20	privKeyPKCS8 := generatePKCS8StringSupress(testPrivKey)
21	privKeyPKCS1 := generatePKCS1String(testPrivKey)
22	testcases := []tcParseDSN{
23		{
24			dsn: "user:pass@ac-1-laksdnflaf.global/db/schema",
25			config: &Config{
26				Account: "ac-1", User: "user", Password: "pass", Region: "global",
27				Protocol: "https", Host: "ac-1-laksdnflaf.global.snowflakecomputing.com", Port: 443,
28				Database: "db", Schema: "schema",
29				OCSPFailOpen:              OCSPFailOpenTrue,
30				ValidateDefaultParameters: ConfigBoolTrue,
31			},
32			ocspMode: ocspModeFailOpen,
33			err:      nil,
34		},
35		{
36			dsn: "user:pass@ac-laksdnflaf.global/db/schema",
37			config: &Config{
38				Account: "ac", User: "user", Password: "pass", Region: "global",
39				Protocol: "https", Host: "ac-laksdnflaf.global.snowflakecomputing.com", Port: 443,
40				Database: "db", Schema: "schema",
41				OCSPFailOpen:              OCSPFailOpenTrue,
42				ValidateDefaultParameters: ConfigBoolTrue,
43			},
44			ocspMode: ocspModeFailOpen,
45			err:      nil,
46		},
47		{
48			dsn: "u:p@asnowflakecomputing.com/db/pa?account=a&protocol=https&role=r&timezone=UTC&aehouse=w",
49			config: &Config{Account: "a", User: "u", Password: "p", Database: "db", Schema: "pa",
50				Protocol: "https", Role: "r", Host: "asnowflakecomputing.com.snowflakecomputing.com", Port: 443, Region: "com",
51				OCSPFailOpen:              OCSPFailOpenTrue,
52				ValidateDefaultParameters: ConfigBoolTrue,
53			},
54			ocspMode: ocspModeFailOpen,
55			err:      nil,
56		},
57		{
58			dsn: "u:p@/db?account=ac",
59			config: &Config{
60				Account: "ac", User: "u", Password: "p", Database: "db",
61				Protocol: "https", Host: "ac.snowflakecomputing.com", Port: 443,
62				OCSPFailOpen:              OCSPFailOpenTrue,
63				ValidateDefaultParameters: ConfigBoolTrue,
64			},
65			ocspMode: ocspModeFailOpen,
66			err:      nil,
67		},
68		{
69			dsn: "user:pass@account-hfdw89q748ew9gqf48w9qgf.global/db/s",
70			config: &Config{
71				Account: "account", User: "user", Password: "pass", Region: "global",
72				Protocol: "https", Host: "account-hfdw89q748ew9gqf48w9qgf.global.snowflakecomputing.com", Port: 443,
73				Database: "db", Schema: "s",
74				ValidateDefaultParameters: ConfigBoolTrue,
75				OCSPFailOpen:              OCSPFailOpenTrue,
76			},
77			ocspMode: ocspModeFailOpen,
78			err:      nil,
79		},
80		{
81			dsn: "user:pass@account-hfdw89q748ew9gqf48w9qgf/db/s",
82			config: &Config{
83				Account: "account-hfdw89q748ew9gqf48w9qgf", User: "user", Password: "pass", Region: "",
84				Protocol: "https", Host: "account-hfdw89q748ew9gqf48w9qgf.snowflakecomputing.com", Port: 443,
85				Database: "db", Schema: "s",
86				ValidateDefaultParameters: ConfigBoolTrue,
87				OCSPFailOpen:              OCSPFailOpenTrue,
88			},
89			ocspMode: ocspModeFailOpen,
90			err:      nil,
91		},
92		{
93			dsn: "user:pass@account",
94			config: &Config{
95				Account: "account", User: "user", Password: "pass", Region: "",
96				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
97				OCSPFailOpen:              OCSPFailOpenTrue,
98				ValidateDefaultParameters: ConfigBoolTrue,
99			},
100			ocspMode: ocspModeFailOpen,
101			err:      nil,
102		},
103		{
104			dsn: "user:pass@account.eu-faraway",
105			config: &Config{
106				Account: "account", User: "user", Password: "pass", Region: "eu-faraway",
107				Protocol: "https", Host: "account.eu-faraway.snowflakecomputing.com", Port: 443,
108				OCSPFailOpen:              OCSPFailOpenTrue,
109				ValidateDefaultParameters: ConfigBoolTrue,
110			},
111			ocspMode: ocspModeFailOpen,
112			err:      nil,
113		},
114		{
115			dsn: "user:pass@account?region=eu-faraway",
116			config: &Config{
117				Account: "account", User: "user", Password: "pass", Region: "eu-faraway",
118				Protocol: "https", Host: "account.eu-faraway.snowflakecomputing.com", Port: 443,
119				OCSPFailOpen:              OCSPFailOpenTrue,
120				ValidateDefaultParameters: ConfigBoolTrue,
121			},
122			ocspMode: ocspModeFailOpen,
123			err:      nil,
124		},
125		{
126			dsn: "user:pass@account/db",
127			config: &Config{
128				Account: "account", User: "user", Password: "pass",
129				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
130				Database:                  "db",
131				OCSPFailOpen:              OCSPFailOpenTrue,
132				ValidateDefaultParameters: ConfigBoolTrue,
133			},
134			ocspMode: ocspModeFailOpen,
135			err:      nil,
136		},
137		{
138			dsn: "user:pass@host:123/db/schema?account=ac&protocol=http",
139			config: &Config{
140				Account: "ac", User: "user", Password: "pass",
141				Protocol: "http", Host: "host", Port: 123,
142				Database: "db", Schema: "schema",
143				OCSPFailOpen:              OCSPFailOpenTrue,
144				ValidateDefaultParameters: ConfigBoolTrue,
145			},
146			ocspMode: ocspModeFailOpen,
147			err:      nil,
148		},
149		{
150			dsn: "user@host:123/db/schema?account=ac&protocol=http",
151			config: &Config{
152				Account: "ac", User: "user", Password: "pass",
153				Protocol: "http", Host: "host", Port: 123,
154				Database: "db", Schema: "schema",
155				OCSPFailOpen:              OCSPFailOpenTrue,
156				ValidateDefaultParameters: ConfigBoolTrue,
157			},
158			ocspMode: ocspModeFailOpen,
159			err:      ErrEmptyPassword,
160		},
161		{
162			dsn: "@host:123/db/schema?account=ac&protocol=http",
163			config: &Config{
164				Account: "ac", User: "user", Password: "pass",
165				Protocol: "http", Host: "host", Port: 123,
166				Database: "db", Schema: "schema",
167				OCSPFailOpen:              OCSPFailOpenTrue,
168				ValidateDefaultParameters: ConfigBoolTrue,
169			},
170			ocspMode: ocspModeFailOpen,
171			err:      ErrEmptyUsername,
172		},
173		{
174			dsn: "user:p@host:123/db/schema?protocol=http",
175			config: &Config{
176				Account: "ac", User: "user", Password: "pass",
177				Protocol: "http", Host: "host", Port: 123,
178				Database: "db", Schema: "schema",
179				OCSPFailOpen:              OCSPFailOpenTrue,
180				ValidateDefaultParameters: ConfigBoolTrue,
181			},
182			ocspMode: ocspModeFailOpen,
183			err:      ErrEmptyAccount,
184		},
185		{
186			dsn: "u:p@a.snowflakecomputing.com/db/pa?account=a&protocol=https&role=r&timezone=UTC&warehouse=w",
187			config: &Config{
188				Account: "a", User: "u", Password: "p",
189				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
190				Database: "db", Schema: "pa", Role: "r", Warehouse: "w",
191				OCSPFailOpen:              OCSPFailOpenTrue,
192				ValidateDefaultParameters: ConfigBoolTrue,
193			},
194			ocspMode: ocspModeFailOpen,
195			err:      nil,
196		},
197		{
198			dsn: "u:p@snowflake.local:9876?account=a&protocol=http",
199			config: &Config{
200				Account: "a", User: "u", Password: "p",
201				Protocol: "http", Host: "snowflake.local", Port: 9876,
202				OCSPFailOpen:              OCSPFailOpenTrue,
203				ValidateDefaultParameters: ConfigBoolTrue,
204			},
205			ocspMode: ocspModeFailOpen,
206			err:      nil,
207		},
208		{
209			dsn: "snowflake.local:9876?account=a&protocol=http&authenticator=OAUTH",
210			config: &Config{
211				Account: "a", Authenticator: AuthTypeOAuth,
212				Protocol: "http", Host: "snowflake.local", Port: 9876,
213				OCSPFailOpen:              OCSPFailOpenTrue,
214				ValidateDefaultParameters: ConfigBoolTrue,
215			},
216			ocspMode: ocspModeFailOpen,
217			err:      nil,
218		},
219		{
220			dsn: "u:@a.snowflake.local:9876?account=a&protocol=http&authenticator=SNOWFLAKE_JWT",
221			config: &Config{
222				Account: "a", User: "u", Authenticator: AuthTypeJwt,
223				Protocol: "http", Host: "a.snowflake.local", Port: 9876,
224				OCSPFailOpen:              OCSPFailOpenTrue,
225				ValidateDefaultParameters: ConfigBoolTrue,
226			},
227			ocspMode: ocspModeFailOpen,
228			err:      nil,
229		},
230
231		{
232			dsn: "u:p@a?database=d&jwtTimeout=20",
233			config: &Config{
234				Account: "a", User: "u", Password: "p",
235				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
236				Database: "d", Schema: "",
237				JWTExpireTimeout:          20 * time.Second,
238				OCSPFailOpen:              OCSPFailOpenTrue,
239				ValidateDefaultParameters: ConfigBoolTrue,
240			},
241			ocspMode: ocspModeFailOpen,
242		},
243		{
244			dsn: "u:p@a?database=d",
245			config: &Config{
246				Account: "a", User: "u", Password: "p",
247				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
248				Database: "d", Schema: "",
249				JWTExpireTimeout:          defaultJWTTimeout,
250				OCSPFailOpen:              OCSPFailOpenTrue,
251				ValidateDefaultParameters: ConfigBoolTrue,
252			},
253			ocspMode: ocspModeFailOpen,
254		},
255		{
256			dsn: "u:p@snowflake.local:NNNN?account=a&protocol=http",
257			config: &Config{
258				Account: "a", User: "u", Password: "p",
259				Protocol: "http", Host: "snowflake.local", Port: 9876,
260				OCSPFailOpen:              OCSPFailOpenTrue,
261				ValidateDefaultParameters: ConfigBoolTrue,
262			},
263			ocspMode: ocspModeFailOpen,
264			err: &SnowflakeError{
265				Message:     errMsgFailedToParsePort,
266				MessageArgs: []interface{}{"NNNN"},
267				Number:      ErrCodeFailedToParsePort,
268			},
269		},
270		{
271			dsn: "u:p@a?database=d&schema=s&role=r&application=aa&authenticator=snowflake&insecureMode=true&passcode=pp&passcodeInPassword=true",
272			config: &Config{
273				Account: "a", User: "u", Password: "p",
274				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
275				Database: "d", Schema: "s", Role: "r", Authenticator: AuthTypeSnowflake, Application: "aa",
276				InsecureMode: true, Passcode: "pp", PasscodeInPassword: true,
277				OCSPFailOpen:              OCSPFailOpenTrue,
278				ValidateDefaultParameters: ConfigBoolTrue,
279			},
280			ocspMode: ocspModeInsecure,
281			err:      nil,
282		},
283		{
284			// schema should be ignored as no value is specified.
285			dsn: "u:p@a?database=d&schema",
286			config: &Config{
287				Account: "a", User: "u", Password: "p",
288				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
289				Database: "d", Schema: "",
290				OCSPFailOpen:              OCSPFailOpenTrue,
291				ValidateDefaultParameters: ConfigBoolTrue,
292			},
293			ocspMode: ocspModeFailOpen,
294			err:      nil,
295		},
296		{
297			dsn:    "u:p@a?database= %Sd",
298			config: &Config{},
299			err:    url.EscapeError(`invalid URL escape`),
300		},
301		{
302			dsn:    "u:p@a?schema= %Sd",
303			config: &Config{},
304			err:    url.EscapeError(`invalid URL escape`),
305		},
306		{
307			dsn:    "u:p@a?warehouse= %Sd",
308			config: &Config{},
309			err:    url.EscapeError(`invalid URL escape`),
310		},
311		{
312			dsn:    "u:p@a?role= %Sd",
313			config: &Config{},
314			err:    url.EscapeError(`invalid URL escape`),
315		},
316		{
317			dsn:    ":/",
318			config: &Config{},
319			err: &SnowflakeError{
320				Number: ErrCodeFailedToParsePort,
321			},
322		},
323		{
324			dsn:    "u:u@/+/+?account=+&=0",
325			config: &Config{},
326			err:    ErrEmptyAccount,
327		},
328		{
329			dsn:    "u:u@/+/+?account=+&=+&=+",
330			config: &Config{},
331			err:    ErrEmptyAccount,
332		},
333		{
334			dsn: "user%40%2F1:p%3A%40s@/db%2F?account=ac",
335			config: &Config{
336				Account: "ac", User: "user@/1", Password: "p:@s", Database: "db/",
337				Protocol: "https", Host: "ac.snowflakecomputing.com", Port: 443,
338				OCSPFailOpen:              OCSPFailOpenTrue,
339				ValidateDefaultParameters: ConfigBoolTrue,
340			},
341			ocspMode: ocspModeFailOpen,
342			err:      nil,
343		},
344		{
345			dsn: fmt.Sprintf("u:p@ac.snowflake.local:9876?account=ac&protocol=http&authenticator=SNOWFLAKE_JWT&privateKey=%v", privKeyPKCS8),
346			config: &Config{
347				Account: "ac", User: "u", Password: "p",
348				Authenticator: AuthTypeJwt, PrivateKey: testPrivKey,
349				Protocol: "http", Host: "ac.snowflake.local", Port: 9876,
350				OCSPFailOpen:              OCSPFailOpenTrue,
351				ValidateDefaultParameters: ConfigBoolTrue,
352			},
353			ocspMode: ocspModeFailOpen,
354			err:      nil,
355		},
356		{
357			dsn: fmt.Sprintf("u:p@ac.snowflake.local:9876?account=ac&protocol=http&authenticator=%v", url.QueryEscape("https://ac.okta.com")),
358			config: &Config{
359				Account: "ac", User: "u", Password: "p",
360				Authenticator: AuthTypeOkta,
361				OktaURL: &url.URL{
362					Scheme: "https",
363					Host:   "ac.okta.com",
364				},
365				PrivateKey: testPrivKey,
366				Protocol:   "http", Host: "ac.snowflake.local", Port: 9876,
367				OCSPFailOpen:              OCSPFailOpenTrue,
368				ValidateDefaultParameters: ConfigBoolTrue,
369			},
370			ocspMode: ocspModeFailOpen,
371			err:      nil,
372		},
373		{
374			dsn: fmt.Sprintf("u:p@a.snowflake.local:9876?account=a&protocol=http&authenticator=SNOWFLAKE_JWT&privateKey=%v", privKeyPKCS1),
375			config: &Config{
376				Account: "a", User: "u", Password: "p",
377				Authenticator: AuthTypeJwt, PrivateKey: testPrivKey,
378				Protocol: "http", Host: "a.snowflake.local", Port: 9876,
379				OCSPFailOpen:              OCSPFailOpenTrue,
380				ValidateDefaultParameters: ConfigBoolTrue,
381			},
382			ocspMode: ocspModeFailOpen,
383			err:      &SnowflakeError{Number: ErrCodePrivateKeyParseError},
384		},
385		{
386			dsn: "user:pass@account/db/s?ocspFailOpen=true",
387			config: &Config{
388				Account: "account", User: "user", Password: "pass",
389				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
390				Database: "db", Schema: "s", OCSPFailOpen: OCSPFailOpenTrue,
391				ValidateDefaultParameters: ConfigBoolTrue,
392			},
393			ocspMode: ocspModeFailOpen,
394			err:      nil,
395		},
396		{
397			dsn: "user:pass@account/db/s?ocspFailOpen=false",
398			config: &Config{
399				Account: "account", User: "user", Password: "pass",
400				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
401				Database: "db", Schema: "s", OCSPFailOpen: OCSPFailOpenFalse,
402				ValidateDefaultParameters: ConfigBoolTrue,
403			},
404			ocspMode: ocspModeFailClosed,
405			err:      nil,
406		},
407		{
408			dsn: "user:pass@account/db/s?insecureMode=true&ocspFailOpen=false",
409			config: &Config{
410				Account: "account", User: "user", Password: "pass",
411				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
412				Database: "db", Schema: "s", OCSPFailOpen: OCSPFailOpenFalse, InsecureMode: true,
413				ValidateDefaultParameters: ConfigBoolTrue,
414			},
415			ocspMode: ocspModeInsecure,
416			err:      nil,
417		},
418		{
419			dsn: "user:pass@account/db/s?validateDefaultParameters=true",
420			config: &Config{
421				Account: "account", User: "user", Password: "pass",
422				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
423				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolTrue, OCSPFailOpen: OCSPFailOpenTrue,
424			},
425			ocspMode: ocspModeFailOpen,
426			err:      nil,
427		},
428		{
429			dsn: "user:pass@account/db/s?validateDefaultParameters=false",
430			config: &Config{
431				Account: "account", User: "user", Password: "pass",
432				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
433				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolFalse, OCSPFailOpen: OCSPFailOpenTrue,
434			},
435			ocspMode: ocspModeFailOpen,
436			err:      nil,
437		},
438		{
439			dsn: "u:p@a.r.c.snowflakecomputing.com/db/s?account=a.r.c&validateDefaultParameters=false",
440			config: &Config{
441				Account: "a", User: "u", Password: "p",
442				Protocol: "https", Host: "a.r.c.snowflakecomputing.com", Port: 443,
443				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolFalse, OCSPFailOpen: OCSPFailOpenTrue,
444			},
445			ocspMode: ocspModeFailOpen,
446			err:      nil,
447		},
448	}
449
450	for i, test := range testcases {
451		// t.Logf("Parsing testcase %d, DSN: %s", i, test.dsn)
452		cfg, err := ParseDSN(test.dsn)
453		switch {
454		case test.err == nil:
455			if err != nil {
456				t.Fatalf("%d: Failed to parse the DSN. dsn: %v, err: %v", i, test.dsn, err)
457			}
458			if test.config.Host != cfg.Host {
459				t.Fatalf("%d: Failed to match host. expected: %v, got: %v",
460					i, test.config.Host, cfg.Host)
461			}
462			if test.config.Account != cfg.Account {
463				t.Fatalf("%d: Failed to match account. expected: %v, got: %v",
464					i, test.config.Account, cfg.Account)
465			}
466			if test.config.User != cfg.User {
467				t.Fatalf("%d: Failed to match user. expected: %v, got: %v",
468					i, test.config.User, cfg.User)
469			}
470			if test.config.Password != cfg.Password {
471				t.Fatalf("%d: Failed to match password. expected: %v, got: %v",
472					i, test.config.Password, cfg.Password)
473			}
474			if test.config.Database != cfg.Database {
475				t.Fatalf("%d: Failed to match database. expected: %v, got: %v",
476					i, test.config.Database, cfg.Database)
477			}
478			if test.config.Schema != cfg.Schema {
479				t.Fatalf("%d: Failed to match schema. expected: %v, got: %v",
480					i, test.config.Schema, cfg.Schema)
481			}
482			if test.config.Warehouse != cfg.Warehouse {
483				t.Fatalf("%d: Failed to match warehouse. expected: %v, got: %v",
484					i, test.config.Warehouse, cfg.Warehouse)
485			}
486			if test.config.Role != cfg.Role {
487				t.Fatalf("%d: Failed to match role. expected: %v, got: %v",
488					i, test.config.Role, cfg.Role)
489			}
490			if test.config.Region != cfg.Region {
491				t.Fatalf("%d: Failed to match region. expected: %v, got: %v",
492					i, test.config.Region, cfg.Region)
493			}
494			if test.config.Protocol != cfg.Protocol {
495				t.Fatalf("%d: Failed to match protocol. expected: %v, got: %v",
496					i, test.config.Protocol, cfg.Protocol)
497			}
498			if test.config.Passcode != cfg.Passcode {
499				t.Fatalf("%d: Failed to match passcode. expected: %v, got: %v",
500					i, test.config.Passcode, cfg.Passcode)
501			}
502			if test.config.PasscodeInPassword != cfg.PasscodeInPassword {
503				t.Fatalf("%d: Failed to match passcodeInPassword. expected: %v, got: %v",
504					i, test.config.PasscodeInPassword, cfg.PasscodeInPassword)
505			}
506			if test.config.Authenticator != cfg.Authenticator {
507				t.Fatalf("%d: Failed to match Authenticator. expected: %v, got: %v",
508					i, test.config.Authenticator.String(), cfg.Authenticator.String())
509			}
510			if test.config.Authenticator == AuthTypeOkta && *test.config.OktaURL != *cfg.OktaURL {
511				t.Fatalf("%d: Failed to match okta URL. expected: %v, got: %v",
512					i, test.config.OktaURL, cfg.OktaURL)
513			}
514			if test.config.OCSPFailOpen != cfg.OCSPFailOpen {
515				t.Fatalf("%d: Failed to match OCSPFailOpen. expected: %v, got: %v",
516					i, test.config.OCSPFailOpen, cfg.OCSPFailOpen)
517			}
518			if test.ocspMode != cfg.ocspMode() {
519				t.Fatalf("%d: Failed to match OCSPMode. expected: %v, got: %v",
520					i, test.ocspMode, cfg.ocspMode())
521			}
522			if test.config.ValidateDefaultParameters != cfg.ValidateDefaultParameters {
523				t.Fatalf("%d: Failed to match ValidateDefaultParameters. expected: %v, got: %v",
524					i, test.config.ValidateDefaultParameters, cfg.ValidateDefaultParameters)
525			}
526		case test.err != nil:
527			driverErrE, okE := test.err.(*SnowflakeError)
528			driverErrG, okG := err.(*SnowflakeError)
529			if okE && !okG || !okE && okG {
530				t.Fatalf("%d: Wrong error. expected: %v, got: %v", i, test.err, err)
531			}
532			if okE && okG {
533				if driverErrE.Number != driverErrG.Number {
534					t.Fatalf("%d: Wrong error number. expected: %v, got: %v", i, driverErrE.Number, driverErrG.Number)
535				}
536			} else {
537				t1 := reflect.TypeOf(err)
538				t2 := reflect.TypeOf(test.err)
539				if t1 != t2 {
540					t.Fatalf("%d: Wrong error. expected: %T:%v, got: %T:%v", i, test.err, test.err, err, err)
541				}
542			}
543		}
544	}
545}
546
547type tcDSN struct {
548	cfg *Config
549	dsn string
550	err error
551}
552
553func TestDSN(t *testing.T) {
554	tmfmt := "MM-DD-YYYY"
555
556	testcases := []tcDSN{
557		{
558			cfg: &Config{
559				User:     "u",
560				Password: "p",
561				Account:  "a-aofnadsf.somewhere.azure",
562			},
563			dsn: "u:p@a-aofnadsf.somewhere.azure.snowflakecomputing.com:443?ocspFailOpen=true&region=somewhere.azure&validateDefaultParameters=true",
564		},
565		{
566			cfg: &Config{
567				User:     "u",
568				Password: "p",
569				Account:  "a-aofnadsf.global",
570			},
571			dsn: "u:p@a-aofnadsf.global.snowflakecomputing.com:443?ocspFailOpen=true&region=global&validateDefaultParameters=true",
572		},
573		{
574			cfg: &Config{
575				User:     "u",
576				Password: "p",
577				Account:  "a-aofnadsf.global",
578				Region:   "us-west-2",
579			},
580			dsn: "u:p@a-aofnadsf.global.snowflakecomputing.com:443?ocspFailOpen=true&region=global&validateDefaultParameters=true",
581		},
582		{
583			cfg: &Config{
584				User:     "u",
585				Password: "p",
586				Account:  "a-aofnadsf.global",
587				Region:   "r",
588			},
589			err: ErrInvalidRegion,
590		},
591		{
592			cfg: &Config{
593				User:     "u",
594				Password: "p",
595				Account:  "a",
596			},
597			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=true&validateDefaultParameters=true",
598		},
599		{
600			cfg: &Config{
601				User:     "u",
602				Password: "p",
603				Account:  "a",
604				Region:   "us-west-2",
605			},
606			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=true&validateDefaultParameters=true",
607		},
608		{
609			cfg: &Config{
610				User:     "u",
611				Password: "p",
612				Account:  "a",
613				Region:   "r",
614			},
615			dsn: "u:p@a.r.snowflakecomputing.com:443?ocspFailOpen=true&region=r&validateDefaultParameters=true",
616		},
617		{
618			cfg: &Config{
619				User:     "",
620				Password: "p",
621				Account:  "a",
622			},
623			err: ErrEmptyUsername,
624		},
625		{
626			cfg: &Config{
627				User:     "u",
628				Password: "",
629				Account:  "a",
630			},
631			err: ErrEmptyPassword,
632		},
633		{
634			cfg: &Config{
635				User:     "u",
636				Password: "p",
637				Account:  "",
638			},
639			err: ErrEmptyAccount,
640		},
641		{
642			cfg: &Config{
643				User:     "u",
644				Password: "p",
645				Account:  "a.e",
646			},
647			dsn: "u:p@a.e.snowflakecomputing.com:443?ocspFailOpen=true&region=e&validateDefaultParameters=true",
648		},
649		{
650			cfg: &Config{
651				User:     "u",
652				Password: "p",
653				Account:  "a.e",
654				Region:   "us-west-2",
655			},
656			dsn: "u:p@a.e.snowflakecomputing.com:443?ocspFailOpen=true&region=e&validateDefaultParameters=true",
657		},
658		{
659			cfg: &Config{
660				User:     "u",
661				Password: "p",
662				Account:  "a.e",
663				Region:   "r",
664			},
665			err: ErrInvalidRegion,
666		},
667		{
668			cfg: &Config{
669				User:               "u",
670				Password:           "p",
671				Account:            "a",
672				Database:           "db",
673				Schema:             "sc",
674				Role:               "ro",
675				Region:             "b",
676				Authenticator:      AuthTypeSnowflake,
677				Passcode:           "db",
678				PasscodeInPassword: true,
679				LoginTimeout:       10 * time.Second,
680				RequestTimeout:     300 * time.Second,
681				Application:        "special go",
682			},
683			dsn: "u:p@a.b.snowflakecomputing.com:443?application=special+go&database=db&loginTimeout=10&ocspFailOpen=true&passcode=db&passcodeInPassword=true&region=b&requestTimeout=300&role=ro&schema=sc&validateDefaultParameters=true",
684		},
685		{
686			cfg: &Config{
687				User:          "u",
688				Password:      "p",
689				Account:       "a",
690				Authenticator: AuthTypeExternalBrowser,
691			},
692			dsn: "u:p@a.snowflakecomputing.com:443?authenticator=externalbrowser&ocspFailOpen=true&validateDefaultParameters=true",
693		},
694		{
695			cfg: &Config{
696				User:          "u",
697				Password:      "p",
698				Account:       "a",
699				Authenticator: AuthTypeOkta,
700				OktaURL: &url.URL{
701					Scheme: "https",
702					Host:   "sc.okta.com",
703				},
704			},
705			dsn: "u:p@a.snowflakecomputing.com:443?authenticator=https%3A%2F%2Fsc.okta.com&ocspFailOpen=true&validateDefaultParameters=true",
706		},
707		{
708			cfg: &Config{
709				User:     "u",
710				Password: "p",
711				Account:  "a.e",
712				Params: map[string]*string{
713					"TIMESTAMP_OUTPUT_FORMAT": &tmfmt,
714				},
715			},
716			dsn: "u:p@a.e.snowflakecomputing.com:443?TIMESTAMP_OUTPUT_FORMAT=MM-DD-YYYY&ocspFailOpen=true&region=e&validateDefaultParameters=true",
717		},
718		{
719			cfg: &Config{
720				User:     "u",
721				Password: ":@abc",
722				Account:  "a.e",
723				Params: map[string]*string{
724					"TIMESTAMP_OUTPUT_FORMAT": &tmfmt,
725				},
726			},
727			dsn: "u:%3A%40abc@a.e.snowflakecomputing.com:443?TIMESTAMP_OUTPUT_FORMAT=MM-DD-YYYY&ocspFailOpen=true&region=e&validateDefaultParameters=true",
728		},
729		{
730			cfg: &Config{
731				User:         "u",
732				Password:     "p",
733				Account:      "a",
734				OCSPFailOpen: OCSPFailOpenTrue,
735			},
736			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=true&validateDefaultParameters=true",
737		},
738		{
739			cfg: &Config{
740				User:         "u",
741				Password:     "p",
742				Account:      "a",
743				OCSPFailOpen: OCSPFailOpenFalse,
744			},
745			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=false&validateDefaultParameters=true",
746		},
747		{
748			cfg: &Config{
749				User:                      "u",
750				Password:                  "p",
751				Account:                   "a",
752				ValidateDefaultParameters: ConfigBoolFalse,
753			},
754			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=true&validateDefaultParameters=false",
755		},
756		{
757			cfg: &Config{
758				User:                      "u",
759				Password:                  "p",
760				Account:                   "a",
761				ValidateDefaultParameters: ConfigBoolTrue,
762			},
763			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=true&validateDefaultParameters=true",
764		},
765		{
766			cfg: &Config{
767				User:         "u",
768				Password:     "p",
769				Account:      "a",
770				InsecureMode: true,
771			},
772			dsn: "u:p@a.snowflakecomputing.com:443?insecureMode=true&ocspFailOpen=true&validateDefaultParameters=true",
773		},
774		{
775			cfg: &Config{
776				User:     "u",
777				Password: "p",
778				Account:  "a.b.c",
779			},
780			dsn: "u:p@a.b.c.snowflakecomputing.com:443?ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
781		},
782		{
783			cfg: &Config{
784				User:     "u",
785				Password: "p",
786				Account:  "a.b.c",
787				Region:   "us-west-2",
788			},
789			dsn: "u:p@a.b.c.snowflakecomputing.com:443?ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
790		},
791		{
792			cfg: &Config{
793				User:     "u",
794				Password: "p",
795				Account:  "a.b.c",
796				Region:   "r",
797			},
798			err: ErrInvalidRegion,
799		},
800	}
801	for _, test := range testcases {
802		dsn, err := DSN(test.cfg)
803		if test.err == nil && err == nil {
804			if dsn != test.dsn {
805				t.Errorf("failed to get DSN. expected: %v, got:\n %v", test.dsn, dsn)
806			}
807			_, err := ParseDSN(dsn)
808			if err != nil {
809				t.Errorf("failed to parse DSN. dsn: %v, err: %v", dsn, err)
810			}
811			continue
812		}
813		if test.err != nil && err == nil {
814			t.Errorf("expected error. dsn: %v, err: %v", test.dsn, test.err)
815			continue
816		}
817		if err != nil && test.err == nil {
818			t.Errorf("failed to match. err: %v", err)
819			continue
820		}
821	}
822}
823