github.com/snowflakedb/gosnowflake@v1.9.0/dsn_test.go (about)

     1  // Copyright (c) 2017-2022 Snowflake Computing Inc. All rights reserved.
     2  
     3  package gosnowflake
     4  
     5  import (
     6  	"crypto/ecdsa"
     7  	"crypto/elliptic"
     8  	cr "crypto/rand"
     9  	"crypto/rsa"
    10  	"crypto/x509"
    11  	"encoding/pem"
    12  	"fmt"
    13  	"net/url"
    14  	"os"
    15  	"reflect"
    16  	"strconv"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/aws/smithy-go/rand"
    22  )
    23  
    24  type tcParseDSN struct {
    25  	dsn      string
    26  	config   *Config
    27  	ocspMode string
    28  	err      error
    29  }
    30  
    31  func TestParseDSN(t *testing.T) {
    32  	privKeyPKCS8 := generatePKCS8StringSupress(testPrivKey)
    33  	privKeyPKCS1 := generatePKCS1String(testPrivKey)
    34  	testcases := []tcParseDSN{
    35  		{
    36  			dsn: "user:pass@ac-1-laksdnflaf.global/db/schema",
    37  			config: &Config{
    38  				Account: "ac-1", User: "user", Password: "pass", Region: "global",
    39  				Protocol: "https", Host: "ac-1-laksdnflaf.global.snowflakecomputing.com", Port: 443,
    40  				Database: "db", Schema: "schema",
    41  				OCSPFailOpen:              OCSPFailOpenTrue,
    42  				ValidateDefaultParameters: ConfigBoolTrue,
    43  				ClientTimeout:             defaultClientTimeout,
    44  				JWTClientTimeout:          defaultJWTClientTimeout,
    45  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
    46  				IncludeRetryReason:        ConfigBoolTrue,
    47  			},
    48  			ocspMode: ocspModeFailOpen,
    49  			err:      nil,
    50  		},
    51  		{
    52  			dsn: "user:pass@ac-laksdnflaf.global/db/schema",
    53  			config: &Config{
    54  				Account: "ac", User: "user", Password: "pass", Region: "global",
    55  				Protocol: "https", Host: "ac-laksdnflaf.global.snowflakecomputing.com", Port: 443,
    56  				Database: "db", Schema: "schema",
    57  				OCSPFailOpen:              OCSPFailOpenTrue,
    58  				ValidateDefaultParameters: ConfigBoolTrue,
    59  				ClientTimeout:             defaultClientTimeout,
    60  				JWTClientTimeout:          defaultJWTClientTimeout,
    61  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
    62  				IncludeRetryReason:        ConfigBoolTrue,
    63  			},
    64  			ocspMode: ocspModeFailOpen,
    65  			err:      nil,
    66  		},
    67  		{
    68  			dsn: "u:p@asnowflakecomputing.com/db/pa?account=a&protocol=https&role=r&timezone=UTC&aehouse=w",
    69  			config: &Config{Account: "a", User: "u", Password: "p", Database: "db", Schema: "pa",
    70  				Protocol: "https", Role: "r", Host: "asnowflakecomputing.com.snowflakecomputing.com", Port: 443, Region: "com",
    71  				OCSPFailOpen:              OCSPFailOpenTrue,
    72  				ValidateDefaultParameters: ConfigBoolTrue,
    73  				ClientTimeout:             defaultClientTimeout,
    74  				JWTClientTimeout:          defaultJWTClientTimeout,
    75  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
    76  				IncludeRetryReason:        ConfigBoolTrue,
    77  			},
    78  			ocspMode: ocspModeFailOpen,
    79  			err:      nil,
    80  		},
    81  		{
    82  			dsn: "u:p@/db?account=ac",
    83  			config: &Config{
    84  				Account: "ac", User: "u", Password: "p", Database: "db",
    85  				Protocol: "https", Host: "ac.snowflakecomputing.com", Port: 443,
    86  				OCSPFailOpen:              OCSPFailOpenTrue,
    87  				ValidateDefaultParameters: ConfigBoolTrue,
    88  				ClientTimeout:             defaultClientTimeout,
    89  				JWTClientTimeout:          defaultJWTClientTimeout,
    90  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
    91  				IncludeRetryReason:        ConfigBoolTrue,
    92  			},
    93  			ocspMode: ocspModeFailOpen,
    94  			err:      nil,
    95  		},
    96  		{
    97  			dsn: "user:pass@account-hfdw89q748ew9gqf48w9qgf.global/db/s",
    98  			config: &Config{
    99  				Account: "account", User: "user", Password: "pass", Region: "global",
   100  				Protocol: "https", Host: "account-hfdw89q748ew9gqf48w9qgf.global.snowflakecomputing.com", Port: 443,
   101  				Database: "db", Schema: "s",
   102  				ValidateDefaultParameters: ConfigBoolTrue,
   103  				OCSPFailOpen:              OCSPFailOpenTrue,
   104  				ClientTimeout:             defaultClientTimeout,
   105  				JWTClientTimeout:          defaultJWTClientTimeout,
   106  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   107  				IncludeRetryReason:        ConfigBoolTrue,
   108  			},
   109  			ocspMode: ocspModeFailOpen,
   110  			err:      nil,
   111  		},
   112  		{
   113  			dsn: "user:pass@account-hfdw89q748ew9gqf48w9qgf/db/s",
   114  			config: &Config{
   115  				Account: "account-hfdw89q748ew9gqf48w9qgf", User: "user", Password: "pass", Region: "",
   116  				Protocol: "https", Host: "account-hfdw89q748ew9gqf48w9qgf.snowflakecomputing.com", Port: 443,
   117  				Database: "db", Schema: "s",
   118  				ValidateDefaultParameters: ConfigBoolTrue,
   119  				OCSPFailOpen:              OCSPFailOpenTrue,
   120  				ClientTimeout:             defaultClientTimeout,
   121  				JWTClientTimeout:          defaultJWTClientTimeout,
   122  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   123  				IncludeRetryReason:        ConfigBoolTrue,
   124  			},
   125  			ocspMode: ocspModeFailOpen,
   126  			err:      nil,
   127  		},
   128  		{
   129  			dsn: "user:pass@account",
   130  			config: &Config{
   131  				Account: "account", User: "user", Password: "pass", Region: "",
   132  				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
   133  				OCSPFailOpen:              OCSPFailOpenTrue,
   134  				ValidateDefaultParameters: ConfigBoolTrue,
   135  				ClientTimeout:             defaultClientTimeout,
   136  				JWTClientTimeout:          defaultJWTClientTimeout,
   137  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   138  				IncludeRetryReason:        ConfigBoolTrue,
   139  			},
   140  			ocspMode: ocspModeFailOpen,
   141  			err:      nil,
   142  		},
   143  		{
   144  			dsn: "user:pass@account.eu-faraway",
   145  			config: &Config{
   146  				Account: "account", User: "user", Password: "pass", Region: "eu-faraway",
   147  				Protocol: "https", Host: "account.eu-faraway.snowflakecomputing.com", Port: 443,
   148  				OCSPFailOpen:              OCSPFailOpenTrue,
   149  				ValidateDefaultParameters: ConfigBoolTrue,
   150  				ClientTimeout:             defaultClientTimeout,
   151  				JWTClientTimeout:          defaultJWTClientTimeout,
   152  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   153  				IncludeRetryReason:        ConfigBoolTrue,
   154  			},
   155  			ocspMode: ocspModeFailOpen,
   156  			err:      nil,
   157  		},
   158  		{
   159  			dsn: "user:pass@account?region=eu-faraway",
   160  			config: &Config{
   161  				Account: "account", User: "user", Password: "pass", Region: "eu-faraway",
   162  				Protocol: "https", Host: "account.eu-faraway.snowflakecomputing.com", Port: 443,
   163  				OCSPFailOpen:              OCSPFailOpenTrue,
   164  				ValidateDefaultParameters: ConfigBoolTrue,
   165  				ClientTimeout:             defaultClientTimeout,
   166  				JWTClientTimeout:          defaultJWTClientTimeout,
   167  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   168  				IncludeRetryReason:        ConfigBoolTrue,
   169  			},
   170  			ocspMode: ocspModeFailOpen,
   171  			err:      nil,
   172  		},
   173  		{
   174  			dsn: "user:pass@account/db",
   175  			config: &Config{
   176  				Account: "account", User: "user", Password: "pass",
   177  				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
   178  				Database:                  "db",
   179  				OCSPFailOpen:              OCSPFailOpenTrue,
   180  				ValidateDefaultParameters: ConfigBoolTrue,
   181  				ClientTimeout:             defaultClientTimeout,
   182  				JWTClientTimeout:          defaultJWTClientTimeout,
   183  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   184  				IncludeRetryReason:        ConfigBoolTrue,
   185  			},
   186  			ocspMode: ocspModeFailOpen,
   187  			err:      nil,
   188  		},
   189  		{
   190  			dsn: "user:pass@host:123/db/schema?account=ac&protocol=http",
   191  			config: &Config{
   192  				Account: "ac", User: "user", Password: "pass",
   193  				Protocol: "http", Host: "host", Port: 123,
   194  				Database: "db", Schema: "schema",
   195  				OCSPFailOpen:              OCSPFailOpenTrue,
   196  				ValidateDefaultParameters: ConfigBoolTrue,
   197  				ClientTimeout:             defaultClientTimeout,
   198  				JWTClientTimeout:          defaultJWTClientTimeout,
   199  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   200  				IncludeRetryReason:        ConfigBoolTrue,
   201  			},
   202  			ocspMode: ocspModeFailOpen,
   203  			err:      nil,
   204  		},
   205  		{
   206  			dsn: "user@host:123/db/schema?account=ac&protocol=http",
   207  			config: &Config{
   208  				Account: "ac", User: "user", Password: "pass",
   209  				Protocol: "http", Host: "host", Port: 123,
   210  				Database: "db", Schema: "schema",
   211  				OCSPFailOpen:              OCSPFailOpenTrue,
   212  				ValidateDefaultParameters: ConfigBoolTrue,
   213  				ClientTimeout:             defaultClientTimeout,
   214  				JWTClientTimeout:          defaultJWTClientTimeout,
   215  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   216  				IncludeRetryReason:        ConfigBoolTrue,
   217  			},
   218  			ocspMode: ocspModeFailOpen,
   219  			err:      errEmptyPassword(),
   220  		},
   221  		{
   222  			dsn: "@host:123/db/schema?account=ac&protocol=http",
   223  			config: &Config{
   224  				Account: "ac", User: "user", Password: "pass",
   225  				Protocol: "http", Host: "host", Port: 123,
   226  				Database: "db", Schema: "schema",
   227  				OCSPFailOpen:              OCSPFailOpenTrue,
   228  				ValidateDefaultParameters: ConfigBoolTrue,
   229  				ClientTimeout:             defaultClientTimeout,
   230  				JWTClientTimeout:          defaultJWTClientTimeout,
   231  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   232  				IncludeRetryReason:        ConfigBoolTrue,
   233  			},
   234  			ocspMode: ocspModeFailOpen,
   235  			err:      errEmptyUsername(),
   236  		},
   237  		{
   238  			dsn: "user:p@host:123/db/schema?protocol=http",
   239  			config: &Config{
   240  				Account: "ac", User: "user", Password: "pass",
   241  				Protocol: "http", Host: "host", Port: 123,
   242  				Database: "db", Schema: "schema",
   243  				OCSPFailOpen:              OCSPFailOpenTrue,
   244  				ValidateDefaultParameters: ConfigBoolTrue,
   245  				ClientTimeout:             defaultClientTimeout,
   246  				JWTClientTimeout:          defaultJWTClientTimeout,
   247  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   248  				IncludeRetryReason:        ConfigBoolTrue,
   249  			},
   250  			ocspMode: ocspModeFailOpen,
   251  			err:      errEmptyAccount(),
   252  		},
   253  		{
   254  			dsn: "u:p@a.snowflakecomputing.com/db/pa?account=a&protocol=https&role=r&timezone=UTC&warehouse=w",
   255  			config: &Config{
   256  				Account: "a", User: "u", Password: "p",
   257  				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
   258  				Database: "db", Schema: "pa", Role: "r", Warehouse: "w",
   259  				OCSPFailOpen:              OCSPFailOpenTrue,
   260  				ValidateDefaultParameters: ConfigBoolTrue,
   261  				ClientTimeout:             defaultClientTimeout,
   262  				JWTClientTimeout:          defaultJWTClientTimeout,
   263  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   264  				IncludeRetryReason:        ConfigBoolTrue,
   265  			},
   266  			ocspMode: ocspModeFailOpen,
   267  			err:      nil,
   268  		},
   269  		{
   270  			dsn: "u:p@snowflake.local:9876?account=a&protocol=http",
   271  			config: &Config{
   272  				Account: "a", User: "u", Password: "p",
   273  				Protocol: "http", Host: "snowflake.local", Port: 9876,
   274  				OCSPFailOpen:              OCSPFailOpenTrue,
   275  				ValidateDefaultParameters: ConfigBoolTrue,
   276  				ClientTimeout:             defaultClientTimeout,
   277  				JWTClientTimeout:          defaultJWTClientTimeout,
   278  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   279  				IncludeRetryReason:        ConfigBoolTrue,
   280  			},
   281  			ocspMode: ocspModeFailOpen,
   282  			err:      nil,
   283  		},
   284  		{
   285  			dsn: "snowflake.local:9876?account=a&protocol=http&authenticator=OAUTH",
   286  			config: &Config{
   287  				Account: "a", Authenticator: AuthTypeOAuth,
   288  				Protocol: "http", Host: "snowflake.local", Port: 9876,
   289  				OCSPFailOpen:              OCSPFailOpenTrue,
   290  				ValidateDefaultParameters: ConfigBoolTrue,
   291  				ClientTimeout:             defaultClientTimeout,
   292  				JWTClientTimeout:          defaultJWTClientTimeout,
   293  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   294  				IncludeRetryReason:        ConfigBoolTrue,
   295  			},
   296  			ocspMode: ocspModeFailOpen,
   297  			err:      nil,
   298  		},
   299  		{
   300  			dsn: "u:@a.snowflake.local:9876?account=a&protocol=http&authenticator=SNOWFLAKE_JWT",
   301  			config: &Config{
   302  				Account: "a", User: "u", Authenticator: AuthTypeJwt,
   303  				Protocol: "http", Host: "a.snowflake.local", Port: 9876,
   304  				OCSPFailOpen:              OCSPFailOpenTrue,
   305  				ValidateDefaultParameters: ConfigBoolTrue,
   306  				ClientTimeout:             defaultClientTimeout,
   307  				JWTClientTimeout:          defaultJWTClientTimeout,
   308  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   309  				IncludeRetryReason:        ConfigBoolTrue,
   310  			},
   311  			ocspMode: ocspModeFailOpen,
   312  			err:      nil,
   313  		},
   314  
   315  		{
   316  			dsn: "u:p@a?database=d&jwtTimeout=20",
   317  			config: &Config{
   318  				Account: "a", User: "u", Password: "p",
   319  				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
   320  				Database: "d", Schema: "",
   321  				JWTExpireTimeout:          20 * time.Second,
   322  				OCSPFailOpen:              OCSPFailOpenTrue,
   323  				ValidateDefaultParameters: ConfigBoolTrue,
   324  				ClientTimeout:             defaultClientTimeout,
   325  				JWTClientTimeout:          defaultJWTClientTimeout,
   326  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   327  				IncludeRetryReason:        ConfigBoolTrue,
   328  			},
   329  			ocspMode: ocspModeFailOpen,
   330  		},
   331  		{
   332  			dsn: "u:p@a?database=d&externalBrowserTimeout=20",
   333  			config: &Config{
   334  				Account: "a", User: "u", Password: "p",
   335  				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
   336  				Database: "d", Schema: "",
   337  				ExternalBrowserTimeout:    20 * time.Second,
   338  				OCSPFailOpen:              OCSPFailOpenTrue,
   339  				ValidateDefaultParameters: ConfigBoolTrue,
   340  				ClientTimeout:             defaultClientTimeout,
   341  				JWTClientTimeout:          defaultJWTClientTimeout,
   342  				IncludeRetryReason:        ConfigBoolTrue,
   343  				MaxRetryCount:             defaultMaxRetryCount,
   344  			},
   345  			ocspMode: ocspModeFailOpen,
   346  		},
   347  		{
   348  			dsn: "u:p@a?database=d&maxRetryCount=20",
   349  			config: &Config{
   350  				Account: "a", User: "u", Password: "p",
   351  				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
   352  				Database: "d", Schema: "",
   353  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   354  				OCSPFailOpen:              OCSPFailOpenTrue,
   355  				ValidateDefaultParameters: ConfigBoolTrue,
   356  				ClientTimeout:             defaultClientTimeout,
   357  				JWTClientTimeout:          defaultJWTClientTimeout,
   358  				IncludeRetryReason:        ConfigBoolTrue,
   359  				MaxRetryCount:             20,
   360  			},
   361  			ocspMode: ocspModeFailOpen,
   362  		},
   363  		{
   364  			dsn: "u:p@a?database=d",
   365  			config: &Config{
   366  				Account: "a", User: "u", Password: "p",
   367  				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
   368  				Database: "d", Schema: "",
   369  				JWTExpireTimeout:          defaultJWTTimeout,
   370  				OCSPFailOpen:              OCSPFailOpenTrue,
   371  				ValidateDefaultParameters: ConfigBoolTrue,
   372  				ClientTimeout:             defaultClientTimeout,
   373  				JWTClientTimeout:          defaultJWTClientTimeout,
   374  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   375  				IncludeRetryReason:        ConfigBoolTrue,
   376  			},
   377  			ocspMode: ocspModeFailOpen,
   378  		},
   379  		{
   380  			dsn: "u:p@snowflake.local:NNNN?account=a&protocol=http",
   381  			config: &Config{
   382  				Account: "a", User: "u", Password: "p",
   383  				Protocol: "http", Host: "snowflake.local", Port: 9876,
   384  				OCSPFailOpen:              OCSPFailOpenTrue,
   385  				ValidateDefaultParameters: ConfigBoolTrue,
   386  				ClientTimeout:             defaultClientTimeout,
   387  				JWTClientTimeout:          defaultJWTClientTimeout,
   388  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   389  				IncludeRetryReason:        ConfigBoolTrue,
   390  			},
   391  			ocspMode: ocspModeFailOpen,
   392  			err: &SnowflakeError{
   393  				Message:     errMsgFailedToParsePort,
   394  				MessageArgs: []interface{}{"NNNN"},
   395  				Number:      ErrCodeFailedToParsePort,
   396  			},
   397  		},
   398  		{
   399  			dsn: "u:p@a?database=d&schema=s&role=r&application=aa&authenticator=snowflake&insecureMode=true&passcode=pp&passcodeInPassword=true",
   400  			config: &Config{
   401  				Account: "a", User: "u", Password: "p",
   402  				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
   403  				Database: "d", Schema: "s", Role: "r", Authenticator: AuthTypeSnowflake, Application: "aa",
   404  				InsecureMode: true, Passcode: "pp", PasscodeInPassword: true,
   405  				OCSPFailOpen:              OCSPFailOpenTrue,
   406  				ValidateDefaultParameters: ConfigBoolTrue,
   407  				ClientTimeout:             defaultClientTimeout,
   408  				JWTClientTimeout:          defaultJWTClientTimeout,
   409  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   410  				IncludeRetryReason:        ConfigBoolTrue,
   411  			},
   412  			ocspMode: ocspModeInsecure,
   413  			err:      nil,
   414  		},
   415  		{
   416  			// schema should be ignored as no value is specified.
   417  			dsn: "u:p@a?database=d&schema",
   418  			config: &Config{
   419  				Account: "a", User: "u", Password: "p",
   420  				Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
   421  				Database: "d", Schema: "",
   422  				OCSPFailOpen:              OCSPFailOpenTrue,
   423  				ValidateDefaultParameters: ConfigBoolTrue,
   424  				ClientTimeout:             defaultClientTimeout,
   425  				JWTClientTimeout:          defaultJWTClientTimeout,
   426  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   427  				IncludeRetryReason:        ConfigBoolTrue,
   428  			},
   429  			ocspMode: ocspModeFailOpen,
   430  			err:      nil,
   431  		},
   432  		{
   433  			dsn:    "u:p@a?database= %Sd",
   434  			config: &Config{},
   435  			err:    url.EscapeError(`invalid URL escape`),
   436  		},
   437  		{
   438  			dsn:    "u:p@a?schema= %Sd",
   439  			config: &Config{},
   440  			err:    url.EscapeError(`invalid URL escape`),
   441  		},
   442  		{
   443  			dsn:    "u:p@a?warehouse= %Sd",
   444  			config: &Config{},
   445  			err:    url.EscapeError(`invalid URL escape`),
   446  		},
   447  		{
   448  			dsn:    "u:p@a?role= %Sd",
   449  			config: &Config{},
   450  			err:    url.EscapeError(`invalid URL escape`),
   451  		},
   452  		{
   453  			dsn:    ":/",
   454  			config: &Config{},
   455  			err: &SnowflakeError{
   456  				Number: ErrCodeFailedToParsePort,
   457  			},
   458  		},
   459  		{
   460  			dsn:    "u:u@/+/+?account=+&=0",
   461  			config: &Config{},
   462  			err:    errEmptyAccount(),
   463  		},
   464  		{
   465  			dsn:    "u:u@/+/+?account=+&=+&=+",
   466  			config: &Config{},
   467  			err:    errEmptyAccount(),
   468  		},
   469  		{
   470  			dsn: "user%40%2F1:p%3A%40s@/db%2F?account=ac",
   471  			config: &Config{
   472  				Account: "ac", User: "user@/1", Password: "p:@s", Database: "db/",
   473  				Protocol: "https", Host: "ac.snowflakecomputing.com", Port: 443,
   474  				OCSPFailOpen:              OCSPFailOpenTrue,
   475  				ValidateDefaultParameters: ConfigBoolTrue,
   476  				ClientTimeout:             defaultClientTimeout,
   477  				JWTClientTimeout:          defaultJWTClientTimeout,
   478  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   479  				IncludeRetryReason:        ConfigBoolTrue,
   480  			},
   481  			ocspMode: ocspModeFailOpen,
   482  			err:      nil,
   483  		},
   484  		{
   485  			dsn: fmt.Sprintf("u:p@ac.snowflake.local:9876?account=ac&protocol=http&authenticator=SNOWFLAKE_JWT&privateKey=%v", privKeyPKCS8),
   486  			config: &Config{
   487  				Account: "ac", User: "u", Password: "p",
   488  				Authenticator: AuthTypeJwt, PrivateKey: testPrivKey,
   489  				Protocol: "http", Host: "ac.snowflake.local", Port: 9876,
   490  				OCSPFailOpen:              OCSPFailOpenTrue,
   491  				ValidateDefaultParameters: ConfigBoolTrue,
   492  				ClientTimeout:             defaultClientTimeout,
   493  				JWTClientTimeout:          defaultJWTClientTimeout,
   494  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   495  				IncludeRetryReason:        ConfigBoolTrue,
   496  			},
   497  			ocspMode: ocspModeFailOpen,
   498  			err:      nil,
   499  		},
   500  		{
   501  			dsn: fmt.Sprintf("u:p@ac.snowflake.local:9876?account=ac&protocol=http&authenticator=%v", url.QueryEscape("https://ac.okta.com")),
   502  			config: &Config{
   503  				Account: "ac", User: "u", Password: "p",
   504  				Authenticator: AuthTypeOkta,
   505  				OktaURL: &url.URL{
   506  					Scheme: "https",
   507  					Host:   "ac.okta.com",
   508  				},
   509  				PrivateKey: testPrivKey,
   510  				Protocol:   "http", Host: "ac.snowflake.local", Port: 9876,
   511  				OCSPFailOpen:              OCSPFailOpenTrue,
   512  				ValidateDefaultParameters: ConfigBoolTrue,
   513  				ClientTimeout:             defaultClientTimeout,
   514  				JWTClientTimeout:          defaultJWTClientTimeout,
   515  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   516  				IncludeRetryReason:        ConfigBoolTrue,
   517  			},
   518  			ocspMode: ocspModeFailOpen,
   519  			err:      nil,
   520  		},
   521  		{
   522  			dsn: fmt.Sprintf("u:p@a.snowflake.local:9876?account=a&protocol=http&authenticator=SNOWFLAKE_JWT&privateKey=%v", privKeyPKCS1),
   523  			config: &Config{
   524  				Account: "a", User: "u", Password: "p",
   525  				Authenticator: AuthTypeJwt, PrivateKey: testPrivKey,
   526  				Protocol: "http", Host: "a.snowflake.local", Port: 9876,
   527  				OCSPFailOpen:              OCSPFailOpenTrue,
   528  				ValidateDefaultParameters: ConfigBoolTrue,
   529  				ClientTimeout:             defaultClientTimeout,
   530  				JWTClientTimeout:          defaultJWTClientTimeout,
   531  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   532  				IncludeRetryReason:        ConfigBoolTrue,
   533  			},
   534  			ocspMode: ocspModeFailOpen,
   535  			err:      &SnowflakeError{Number: ErrCodePrivateKeyParseError},
   536  		},
   537  		{
   538  			dsn: "user:pass@account/db/s?ocspFailOpen=true",
   539  			config: &Config{
   540  				Account: "account", User: "user", Password: "pass",
   541  				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
   542  				Database: "db", Schema: "s", OCSPFailOpen: OCSPFailOpenTrue,
   543  				ValidateDefaultParameters: ConfigBoolTrue,
   544  				ClientTimeout:             defaultClientTimeout,
   545  				JWTClientTimeout:          defaultJWTClientTimeout,
   546  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   547  				IncludeRetryReason:        ConfigBoolTrue,
   548  			},
   549  			ocspMode: ocspModeFailOpen,
   550  			err:      nil,
   551  		},
   552  		{
   553  			dsn: "user:pass@account/db/s?ocspFailOpen=false",
   554  			config: &Config{
   555  				Account: "account", User: "user", Password: "pass",
   556  				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
   557  				Database: "db", Schema: "s", OCSPFailOpen: OCSPFailOpenFalse,
   558  				ValidateDefaultParameters: ConfigBoolTrue,
   559  				ClientTimeout:             defaultClientTimeout,
   560  				JWTClientTimeout:          defaultJWTClientTimeout,
   561  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   562  				IncludeRetryReason:        ConfigBoolTrue,
   563  			},
   564  			ocspMode: ocspModeFailClosed,
   565  			err:      nil,
   566  		},
   567  		{
   568  			dsn: "user:pass@account/db/s?insecureMode=true&ocspFailOpen=false",
   569  			config: &Config{
   570  				Account: "account", User: "user", Password: "pass",
   571  				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
   572  				Database: "db", Schema: "s", OCSPFailOpen: OCSPFailOpenFalse, InsecureMode: true,
   573  				ValidateDefaultParameters: ConfigBoolTrue,
   574  				ClientTimeout:             defaultClientTimeout,
   575  				JWTClientTimeout:          defaultJWTClientTimeout,
   576  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   577  				IncludeRetryReason:        ConfigBoolTrue,
   578  			},
   579  			ocspMode: ocspModeInsecure,
   580  			err:      nil,
   581  		},
   582  		{
   583  			dsn: "user:pass@account/db/s?validateDefaultParameters=true",
   584  			config: &Config{
   585  				Account: "account", User: "user", Password: "pass",
   586  				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
   587  				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolTrue, OCSPFailOpen: OCSPFailOpenTrue,
   588  				ClientTimeout:          defaultClientTimeout,
   589  				JWTClientTimeout:       defaultJWTClientTimeout,
   590  				ExternalBrowserTimeout: defaultExternalBrowserTimeout,
   591  				IncludeRetryReason:     ConfigBoolTrue,
   592  			},
   593  			ocspMode: ocspModeFailOpen,
   594  			err:      nil,
   595  		},
   596  		{
   597  			dsn: "user:pass@account/db/s?validateDefaultParameters=false",
   598  			config: &Config{
   599  				Account: "account", User: "user", Password: "pass",
   600  				Protocol: "https", Host: "account.snowflakecomputing.com", Port: 443,
   601  				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolFalse, OCSPFailOpen: OCSPFailOpenTrue,
   602  				ClientTimeout:          defaultClientTimeout,
   603  				JWTClientTimeout:       defaultJWTClientTimeout,
   604  				ExternalBrowserTimeout: defaultExternalBrowserTimeout,
   605  				IncludeRetryReason:     ConfigBoolTrue,
   606  			},
   607  			ocspMode: ocspModeFailOpen,
   608  			err:      nil,
   609  		},
   610  		{
   611  			dsn: "u:p@a.r.c.snowflakecomputing.com/db/s?account=a.r.c&validateDefaultParameters=false",
   612  			config: &Config{
   613  				Account: "a", User: "u", Password: "p",
   614  				Protocol: "https", Host: "a.r.c.snowflakecomputing.com", Port: 443,
   615  				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolFalse, OCSPFailOpen: OCSPFailOpenTrue,
   616  				ClientTimeout:          defaultClientTimeout,
   617  				JWTClientTimeout:       defaultJWTClientTimeout,
   618  				ExternalBrowserTimeout: defaultExternalBrowserTimeout,
   619  				IncludeRetryReason:     ConfigBoolTrue,
   620  			},
   621  			ocspMode: ocspModeFailOpen,
   622  			err:      nil,
   623  		},
   624  		{
   625  			dsn: "u:p@a.r.c.snowflakecomputing.com/db/s?account=a.r.c&clientTimeout=300&jwtClientTimeout=45&includeRetryReason=false",
   626  			config: &Config{
   627  				Account: "a", User: "u", Password: "p",
   628  				Protocol: "https", Host: "a.r.c.snowflakecomputing.com", Port: 443,
   629  				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolTrue, OCSPFailOpen: OCSPFailOpenTrue,
   630  				ClientTimeout:            300 * time.Second,
   631  				JWTClientTimeout:         45 * time.Second,
   632  				ExternalBrowserTimeout:   defaultExternalBrowserTimeout,
   633  				DisableQueryContextCache: false,
   634  				IncludeRetryReason:       ConfigBoolFalse,
   635  			},
   636  			ocspMode: ocspModeFailOpen,
   637  			err:      nil,
   638  		},
   639  		{
   640  			dsn: "u:p@a.r.c.snowflakecomputing.com/db/s?account=a.r.c&tmpDirPath=%2Ftmp",
   641  			config: &Config{
   642  				Account: "a", User: "u", Password: "p",
   643  				Protocol: "https", Host: "a.r.c.snowflakecomputing.com", Port: 443,
   644  				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolTrue, OCSPFailOpen: OCSPFailOpenTrue,
   645  				ClientTimeout:          defaultClientTimeout,
   646  				JWTClientTimeout:       defaultJWTClientTimeout,
   647  				ExternalBrowserTimeout: defaultExternalBrowserTimeout,
   648  				TmpDirPath:             "/tmp",
   649  				IncludeRetryReason:     ConfigBoolTrue,
   650  			},
   651  			ocspMode: ocspModeFailOpen,
   652  			err:      nil,
   653  		},
   654  		{
   655  			dsn: "u:p@a.r.c.snowflakecomputing.com/db/s?account=a.r.c&disableQueryContextCache=true",
   656  			config: &Config{
   657  				Account: "a", User: "u", Password: "p",
   658  				Protocol: "https", Host: "a.r.c.snowflakecomputing.com", Port: 443,
   659  				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolTrue, OCSPFailOpen: OCSPFailOpenTrue,
   660  				ClientTimeout:            defaultClientTimeout,
   661  				JWTClientTimeout:         defaultJWTClientTimeout,
   662  				ExternalBrowserTimeout:   defaultExternalBrowserTimeout,
   663  				DisableQueryContextCache: true,
   664  				IncludeRetryReason:       ConfigBoolTrue,
   665  			},
   666  			ocspMode: ocspModeFailOpen,
   667  			err:      nil,
   668  		},
   669  		{
   670  			dsn: "u:p@a.r.c.snowflakecomputing.com/db/s?account=a.r.c&includeRetryReason=true",
   671  			config: &Config{
   672  				Account: "a", User: "u", Password: "p",
   673  				Protocol: "https", Host: "a.r.c.snowflakecomputing.com", Port: 443,
   674  				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolTrue, OCSPFailOpen: OCSPFailOpenTrue,
   675  				ClientTimeout:          defaultClientTimeout,
   676  				JWTClientTimeout:       defaultJWTClientTimeout,
   677  				ExternalBrowserTimeout: defaultExternalBrowserTimeout,
   678  				IncludeRetryReason:     ConfigBoolTrue,
   679  			},
   680  			ocspMode: ocspModeFailOpen,
   681  			err:      nil,
   682  		},
   683  		{
   684  			dsn: "u:p@a.r.c.snowflakecomputing.com/db/s?account=a.r.c&includeRetryReason=true&clientConfigFile=%2FUsers%2Fuser%2Fconfig.json",
   685  			config: &Config{
   686  				Account: "a", User: "u", Password: "p",
   687  				Protocol: "https", Host: "a.r.c.snowflakecomputing.com", Port: 443,
   688  				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolTrue, OCSPFailOpen: OCSPFailOpenTrue,
   689  				ClientTimeout:          defaultClientTimeout,
   690  				JWTClientTimeout:       defaultJWTClientTimeout,
   691  				ExternalBrowserTimeout: defaultExternalBrowserTimeout,
   692  				IncludeRetryReason:     ConfigBoolTrue,
   693  				ClientConfigFile:       "/Users/user/config.json",
   694  			},
   695  			ocspMode: ocspModeFailOpen,
   696  			err:      nil,
   697  		},
   698  		{
   699  			dsn: "u:p@a.r.c.snowflakecomputing.com/db/s?account=a.r.c&includeRetryReason=true&clientConfigFile=c%3A%5CUsers%5Cuser%5Cconfig.json",
   700  			config: &Config{
   701  				Account: "a", User: "u", Password: "p",
   702  				Protocol: "https", Host: "a.r.c.snowflakecomputing.com", Port: 443,
   703  				Database: "db", Schema: "s", ValidateDefaultParameters: ConfigBoolTrue, OCSPFailOpen: OCSPFailOpenTrue,
   704  				ClientTimeout:          defaultClientTimeout,
   705  				JWTClientTimeout:       defaultJWTClientTimeout,
   706  				ExternalBrowserTimeout: defaultExternalBrowserTimeout,
   707  				IncludeRetryReason:     ConfigBoolTrue,
   708  				ClientConfigFile:       "c:\\Users\\user\\config.json",
   709  			},
   710  			ocspMode: ocspModeFailOpen,
   711  			err:      nil,
   712  		},
   713  		{
   714  			dsn: "u:p@a.snowflakecomputing.com:443?authenticator=http%3A%2F%2Fsc.okta.com&ocspFailOpen=true&validateDefaultParameters=true",
   715  			err: errFailedToParseAuthenticator(),
   716  		},
   717  		{
   718  			dsn: "u:p@a.snowflake.local:9876?account=a&protocol=http&authenticator=EXTERNALBROWSER&disableConsoleLogin=true",
   719  			config: &Config{
   720  				Account: "a", User: "u", Password: "p",
   721  				Authenticator: AuthTypeExternalBrowser,
   722  				Protocol:      "http", Host: "a.snowflake.local", Port: 9876,
   723  				OCSPFailOpen:              OCSPFailOpenTrue,
   724  				ValidateDefaultParameters: ConfigBoolTrue,
   725  				ClientTimeout:             defaultClientTimeout,
   726  				JWTClientTimeout:          defaultJWTClientTimeout,
   727  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   728  				IncludeRetryReason:        ConfigBoolTrue,
   729  				DisableConsoleLogin:       ConfigBoolTrue,
   730  			},
   731  			ocspMode: ocspModeFailOpen,
   732  			err:      nil,
   733  		},
   734  		{
   735  			dsn: "u:p@a.snowflake.local:9876?account=a&protocol=http&authenticator=EXTERNALBROWSER&disableConsoleLogin=false",
   736  			config: &Config{
   737  				Account: "a", User: "u", Password: "p",
   738  				Authenticator: AuthTypeExternalBrowser,
   739  				Protocol:      "http", Host: "a.snowflake.local", Port: 9876,
   740  				OCSPFailOpen:              OCSPFailOpenTrue,
   741  				ValidateDefaultParameters: ConfigBoolTrue,
   742  				ClientTimeout:             defaultClientTimeout,
   743  				JWTClientTimeout:          defaultJWTClientTimeout,
   744  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   745  				IncludeRetryReason:        ConfigBoolTrue,
   746  				DisableConsoleLogin:       ConfigBoolFalse,
   747  			},
   748  			ocspMode: ocspModeFailOpen,
   749  			err:      nil,
   750  		},
   751  	}
   752  
   753  	for _, at := range []AuthType{AuthTypeExternalBrowser, AuthTypeOAuth} {
   754  		testcases = append(testcases, tcParseDSN{
   755  			dsn: fmt.Sprintf("@host:777/db/schema?account=ac&protocol=http&authenticator=%v", strings.ToLower(at.String())),
   756  			config: &Config{
   757  				Account: "ac", User: "", Password: "",
   758  				Protocol: "http", Host: "host", Port: 777,
   759  				Database: "db", Schema: "schema",
   760  				OCSPFailOpen:              OCSPFailOpenTrue,
   761  				ValidateDefaultParameters: ConfigBoolTrue,
   762  				ClientTimeout:             defaultClientTimeout,
   763  				JWTClientTimeout:          defaultJWTClientTimeout,
   764  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   765  				IncludeRetryReason:        ConfigBoolTrue,
   766  				Authenticator:             at,
   767  			},
   768  			ocspMode: ocspModeFailOpen,
   769  			err:      nil,
   770  		})
   771  	}
   772  
   773  	for _, at := range []AuthType{AuthTypeSnowflake, AuthTypeUsernamePasswordMFA, AuthTypeJwt} {
   774  		testcases = append(testcases, tcParseDSN{
   775  			dsn: fmt.Sprintf("@host:888/db/schema?account=ac&protocol=http&authenticator=%v", strings.ToLower(at.String())),
   776  			config: &Config{
   777  				Account: "ac", User: "", Password: "",
   778  				Protocol: "http", Host: "host", Port: 888,
   779  				Database: "db", Schema: "schema",
   780  				OCSPFailOpen:              OCSPFailOpenTrue,
   781  				ValidateDefaultParameters: ConfigBoolTrue,
   782  				ClientTimeout:             defaultClientTimeout,
   783  				JWTClientTimeout:          defaultJWTClientTimeout,
   784  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   785  				IncludeRetryReason:        ConfigBoolTrue,
   786  				Authenticator:             at,
   787  			},
   788  			ocspMode: ocspModeFailOpen,
   789  			err:      errEmptyUsername(),
   790  		})
   791  	}
   792  
   793  	for _, at := range []AuthType{AuthTypeSnowflake, AuthTypeUsernamePasswordMFA} {
   794  		testcases = append(testcases, tcParseDSN{
   795  			dsn: fmt.Sprintf("user@host:888/db/schema?account=ac&protocol=http&authenticator=%v", strings.ToLower(at.String())),
   796  			config: &Config{
   797  				Account: "ac", User: "user", Password: "",
   798  				Protocol: "http", Host: "host", Port: 888,
   799  				Database: "db", Schema: "schema",
   800  				OCSPFailOpen:              OCSPFailOpenTrue,
   801  				ValidateDefaultParameters: ConfigBoolTrue,
   802  				ClientTimeout:             defaultClientTimeout,
   803  				JWTClientTimeout:          defaultJWTClientTimeout,
   804  				ExternalBrowserTimeout:    defaultExternalBrowserTimeout,
   805  				IncludeRetryReason:        ConfigBoolTrue,
   806  				Authenticator:             at,
   807  			},
   808  			ocspMode: ocspModeFailOpen,
   809  			err:      errEmptyPassword(),
   810  		})
   811  	}
   812  
   813  	for i, test := range testcases {
   814  		t.Run(test.dsn, func(t *testing.T) {
   815  			cfg, err := ParseDSN(test.dsn)
   816  			switch {
   817  			case test.err == nil:
   818  				if err != nil {
   819  					t.Fatalf("%d: Failed to parse the DSN. dsn: %v, err: %v", i, test.dsn, err)
   820  				}
   821  				if test.config.Host != cfg.Host {
   822  					t.Fatalf("%d: Failed to match host. expected: %v, got: %v",
   823  						i, test.config.Host, cfg.Host)
   824  				}
   825  				if test.config.Account != cfg.Account {
   826  					t.Fatalf("%d: Failed to match account. expected: %v, got: %v",
   827  						i, test.config.Account, cfg.Account)
   828  				}
   829  				if test.config.User != cfg.User {
   830  					t.Fatalf("%d: Failed to match user. expected: %v, got: %v",
   831  						i, test.config.User, cfg.User)
   832  				}
   833  				if test.config.Password != cfg.Password {
   834  					t.Fatalf("%d: Failed to match password. expected: %v, got: %v",
   835  						i, test.config.Password, cfg.Password)
   836  				}
   837  				if test.config.Database != cfg.Database {
   838  					t.Fatalf("%d: Failed to match database. expected: %v, got: %v",
   839  						i, test.config.Database, cfg.Database)
   840  				}
   841  				if test.config.Schema != cfg.Schema {
   842  					t.Fatalf("%d: Failed to match schema. expected: %v, got: %v",
   843  						i, test.config.Schema, cfg.Schema)
   844  				}
   845  				if test.config.Warehouse != cfg.Warehouse {
   846  					t.Fatalf("%d: Failed to match warehouse. expected: %v, got: %v",
   847  						i, test.config.Warehouse, cfg.Warehouse)
   848  				}
   849  				if test.config.Role != cfg.Role {
   850  					t.Fatalf("%d: Failed to match role. expected: %v, got: %v",
   851  						i, test.config.Role, cfg.Role)
   852  				}
   853  				if test.config.Region != cfg.Region {
   854  					t.Fatalf("%d: Failed to match region. expected: %v, got: %v",
   855  						i, test.config.Region, cfg.Region)
   856  				}
   857  				if test.config.Protocol != cfg.Protocol {
   858  					t.Fatalf("%d: Failed to match protocol. expected: %v, got: %v",
   859  						i, test.config.Protocol, cfg.Protocol)
   860  				}
   861  				if test.config.Passcode != cfg.Passcode {
   862  					t.Fatalf("%d: Failed to match passcode. expected: %v, got: %v",
   863  						i, test.config.Passcode, cfg.Passcode)
   864  				}
   865  				if test.config.PasscodeInPassword != cfg.PasscodeInPassword {
   866  					t.Fatalf("%d: Failed to match passcodeInPassword. expected: %v, got: %v",
   867  						i, test.config.PasscodeInPassword, cfg.PasscodeInPassword)
   868  				}
   869  				if test.config.Authenticator != cfg.Authenticator {
   870  					t.Fatalf("%d: Failed to match Authenticator. expected: %v, got: %v",
   871  						i, test.config.Authenticator.String(), cfg.Authenticator.String())
   872  				}
   873  				if test.config.Authenticator == AuthTypeOkta && *test.config.OktaURL != *cfg.OktaURL {
   874  					t.Fatalf("%d: Failed to match okta URL. expected: %v, got: %v",
   875  						i, test.config.OktaURL, cfg.OktaURL)
   876  				}
   877  				if test.config.OCSPFailOpen != cfg.OCSPFailOpen {
   878  					t.Fatalf("%d: Failed to match OCSPFailOpen. expected: %v, got: %v",
   879  						i, test.config.OCSPFailOpen, cfg.OCSPFailOpen)
   880  				}
   881  				if test.ocspMode != cfg.ocspMode() {
   882  					t.Fatalf("%d: Failed to match OCSPMode. expected: %v, got: %v",
   883  						i, test.ocspMode, cfg.ocspMode())
   884  				}
   885  				if test.config.ValidateDefaultParameters != cfg.ValidateDefaultParameters {
   886  					t.Fatalf("%d: Failed to match ValidateDefaultParameters. expected: %v, got: %v",
   887  						i, test.config.ValidateDefaultParameters, cfg.ValidateDefaultParameters)
   888  				}
   889  				if test.config.ClientTimeout != cfg.ClientTimeout {
   890  					t.Fatalf("%d: Failed to match ClientTimeout. expected: %v, got: %v",
   891  						i, test.config.ClientTimeout, cfg.ClientTimeout)
   892  				}
   893  				if test.config.JWTClientTimeout != cfg.JWTClientTimeout {
   894  					t.Fatalf("%d: Failed to match JWTClientTimeout. expected: %v, got: %v",
   895  						i, test.config.JWTClientTimeout, cfg.JWTClientTimeout)
   896  				}
   897  				if test.config.ExternalBrowserTimeout != cfg.ExternalBrowserTimeout {
   898  					t.Fatalf("%d: Failed to match ExternalBrowserTimeout. expected: %v, got: %v",
   899  						i, test.config.ExternalBrowserTimeout, cfg.ExternalBrowserTimeout)
   900  				}
   901  				if test.config.TmpDirPath != cfg.TmpDirPath {
   902  					t.Fatalf("%v: Failed to match TmpDirPatch. expected: %v, got: %v", i, test.config.TmpDirPath, cfg.TmpDirPath)
   903  				}
   904  				if test.config.DisableQueryContextCache != cfg.DisableQueryContextCache {
   905  					t.Fatalf("%v: Failed to match DisableQueryContextCache. expected: %v, got: %v", i, test.config.DisableQueryContextCache, cfg.DisableQueryContextCache)
   906  				}
   907  				if test.config.IncludeRetryReason != cfg.IncludeRetryReason {
   908  					t.Fatalf("%v: Failed to match IncludeRetryReason. expected: %v, got: %v", i, test.config.IncludeRetryReason, cfg.IncludeRetryReason)
   909  				}
   910  				if test.config.DisableConsoleLogin != cfg.DisableConsoleLogin {
   911  					t.Fatalf("%v: Failed to match DisableConsoleLogin. expected: %v, got: %v", i, test.config.DisableConsoleLogin, cfg.DisableConsoleLogin)
   912  				}
   913  				assertEqualF(t, cfg.ClientConfigFile, test.config.ClientConfigFile, "client config file")
   914  			case test.err != nil:
   915  				driverErrE, okE := test.err.(*SnowflakeError)
   916  				driverErrG, okG := err.(*SnowflakeError)
   917  				if okE && !okG || !okE && okG {
   918  					t.Fatalf("%d: Wrong error. expected: %v, got: %v", i, test.err, err)
   919  				}
   920  				if okE && okG {
   921  					if driverErrE.Number != driverErrG.Number {
   922  						t.Fatalf("%d: Wrong error number. expected: %v, got: %v", i, driverErrE.Number, driverErrG.Number)
   923  					}
   924  				} else {
   925  					t1 := reflect.TypeOf(err)
   926  					t2 := reflect.TypeOf(test.err)
   927  					if t1 != t2 {
   928  						t.Fatalf("%d: Wrong error. expected: %T:%v, got: %T:%v", i, test.err, test.err, err, err)
   929  					}
   930  				}
   931  			}
   932  
   933  		})
   934  	}
   935  }
   936  
   937  type tcDSN struct {
   938  	cfg *Config
   939  	dsn string
   940  	err error
   941  }
   942  
   943  func TestDSN(t *testing.T) {
   944  	tmfmt := "MM-DD-YYYY"
   945  	testcases := []tcDSN{
   946  		{
   947  			cfg: &Config{
   948  				User:     "u",
   949  				Password: "p",
   950  				Account:  "a-aofnadsf.somewhere.azure",
   951  			},
   952  			dsn: "u:p@a-aofnadsf.somewhere.azure.snowflakecomputing.com:443?ocspFailOpen=true&region=somewhere.azure&validateDefaultParameters=true",
   953  		},
   954  		{
   955  			cfg: &Config{
   956  				User:     "u",
   957  				Password: "p",
   958  				Account:  "a-aofnadsf.global",
   959  			},
   960  			dsn: "u:p@a-aofnadsf.global.snowflakecomputing.com:443?ocspFailOpen=true&region=global&validateDefaultParameters=true",
   961  		},
   962  		{
   963  			cfg: &Config{
   964  				User:     "u",
   965  				Password: "p",
   966  				Account:  "a-aofnadsf.global",
   967  				Region:   "us-west-2",
   968  			},
   969  			dsn: "u:p@a-aofnadsf.global.snowflakecomputing.com:443?ocspFailOpen=true&region=global&validateDefaultParameters=true",
   970  		},
   971  		{
   972  			cfg: &Config{
   973  				User:     "u",
   974  				Password: "p",
   975  				Account:  "a-aofnadsf.global",
   976  				Region:   "r",
   977  			},
   978  			err: errInvalidRegion(),
   979  		},
   980  		{
   981  			cfg: &Config{
   982  				User:     "u",
   983  				Password: "p",
   984  				Account:  "a",
   985  			},
   986  			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=true&validateDefaultParameters=true",
   987  		},
   988  		{
   989  			cfg: &Config{
   990  				User:     "u",
   991  				Password: "p",
   992  				Account:  "a",
   993  				Region:   "us-west-2",
   994  			},
   995  			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=true&validateDefaultParameters=true",
   996  		},
   997  		{
   998  			cfg: &Config{
   999  				User:     "u",
  1000  				Password: "p",
  1001  				Account:  "a",
  1002  				Region:   "r",
  1003  			},
  1004  			dsn: "u:p@a.r.snowflakecomputing.com:443?ocspFailOpen=true&region=r&validateDefaultParameters=true",
  1005  		},
  1006  		{
  1007  			cfg: &Config{
  1008  				User:                   "u",
  1009  				Password:               "p",
  1010  				Account:                "a",
  1011  				Region:                 "r",
  1012  				ExternalBrowserTimeout: 20 * time.Second,
  1013  			},
  1014  			dsn: "u:p@a.r.snowflakecomputing.com:443?externalBrowserTimeout=20&ocspFailOpen=true&region=r&validateDefaultParameters=true",
  1015  		},
  1016  		{
  1017  			cfg: &Config{
  1018  				User:     "",
  1019  				Password: "p",
  1020  				Account:  "a",
  1021  			},
  1022  			err: errEmptyUsername(),
  1023  		},
  1024  		{
  1025  			cfg: &Config{
  1026  				User:     "u",
  1027  				Password: "",
  1028  				Account:  "a",
  1029  			},
  1030  			err: errEmptyPassword(),
  1031  		},
  1032  		{
  1033  			cfg: &Config{
  1034  				User:     "u",
  1035  				Password: "p",
  1036  				Account:  "",
  1037  			},
  1038  			err: errEmptyAccount(),
  1039  		},
  1040  		{
  1041  			cfg: &Config{
  1042  				User:     "u",
  1043  				Password: "p",
  1044  				Account:  "a.e",
  1045  			},
  1046  			dsn: "u:p@a.e.snowflakecomputing.com:443?ocspFailOpen=true&region=e&validateDefaultParameters=true",
  1047  		},
  1048  		{
  1049  			cfg: &Config{
  1050  				User:     "u",
  1051  				Password: "p",
  1052  				Account:  "a.e",
  1053  				Region:   "us-west-2",
  1054  			},
  1055  			dsn: "u:p@a.e.snowflakecomputing.com:443?ocspFailOpen=true&region=e&validateDefaultParameters=true",
  1056  		},
  1057  		{
  1058  			cfg: &Config{
  1059  				User:     "u",
  1060  				Password: "p",
  1061  				Account:  "a.e",
  1062  				Region:   "r",
  1063  			},
  1064  			err: errInvalidRegion(),
  1065  		},
  1066  		{
  1067  			cfg: &Config{
  1068  				User:               "u",
  1069  				Password:           "p",
  1070  				Account:            "a",
  1071  				Database:           "db",
  1072  				Schema:             "sc",
  1073  				Role:               "ro",
  1074  				Region:             "b",
  1075  				Authenticator:      AuthTypeSnowflake,
  1076  				Passcode:           "db",
  1077  				PasscodeInPassword: true,
  1078  				LoginTimeout:       10 * time.Second,
  1079  				RequestTimeout:     300 * time.Second,
  1080  				Application:        "special go",
  1081  			},
  1082  			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",
  1083  		},
  1084  		{
  1085  			cfg: &Config{
  1086  				User:                           "u",
  1087  				Password:                       "p",
  1088  				Account:                        "a",
  1089  				Authenticator:                  AuthTypeExternalBrowser,
  1090  				ClientStoreTemporaryCredential: ConfigBoolTrue,
  1091  			},
  1092  			dsn: "u:p@a.snowflakecomputing.com:443?authenticator=externalbrowser&clientStoreTemporaryCredential=true&ocspFailOpen=true&validateDefaultParameters=true",
  1093  		},
  1094  		{
  1095  			cfg: &Config{
  1096  				User:                           "u",
  1097  				Password:                       "p",
  1098  				Account:                        "a",
  1099  				Authenticator:                  AuthTypeExternalBrowser,
  1100  				ClientStoreTemporaryCredential: ConfigBoolFalse,
  1101  			},
  1102  			dsn: "u:p@a.snowflakecomputing.com:443?authenticator=externalbrowser&clientStoreTemporaryCredential=false&ocspFailOpen=true&validateDefaultParameters=true",
  1103  		},
  1104  		{
  1105  			cfg: &Config{
  1106  				User:          "u",
  1107  				Password:      "p",
  1108  				Account:       "a",
  1109  				Authenticator: AuthTypeOkta,
  1110  				OktaURL: &url.URL{
  1111  					Scheme: "https",
  1112  					Host:   "sc.okta.com",
  1113  				},
  1114  			},
  1115  			dsn: "u:p@a.snowflakecomputing.com:443?authenticator=https%3A%2F%2Fsc.okta.com&ocspFailOpen=true&validateDefaultParameters=true",
  1116  		},
  1117  		{
  1118  			cfg: &Config{
  1119  				User:     "u",
  1120  				Password: "p",
  1121  				Account:  "a.e",
  1122  				Params: map[string]*string{
  1123  					"TIMESTAMP_OUTPUT_FORMAT": &tmfmt,
  1124  				},
  1125  			},
  1126  			dsn: "u:p@a.e.snowflakecomputing.com:443?TIMESTAMP_OUTPUT_FORMAT=MM-DD-YYYY&ocspFailOpen=true&region=e&validateDefaultParameters=true",
  1127  		},
  1128  		{
  1129  			cfg: &Config{
  1130  				User:     "u",
  1131  				Password: ":@abc",
  1132  				Account:  "a.e",
  1133  				Params: map[string]*string{
  1134  					"TIMESTAMP_OUTPUT_FORMAT": &tmfmt,
  1135  				},
  1136  			},
  1137  			dsn: "u:%3A%40abc@a.e.snowflakecomputing.com:443?TIMESTAMP_OUTPUT_FORMAT=MM-DD-YYYY&ocspFailOpen=true&region=e&validateDefaultParameters=true",
  1138  		},
  1139  		{
  1140  			cfg: &Config{
  1141  				User:         "u",
  1142  				Password:     "p",
  1143  				Account:      "a",
  1144  				OCSPFailOpen: OCSPFailOpenTrue,
  1145  			},
  1146  			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=true&validateDefaultParameters=true",
  1147  		},
  1148  		{
  1149  			cfg: &Config{
  1150  				User:         "u",
  1151  				Password:     "p",
  1152  				Account:      "a",
  1153  				OCSPFailOpen: OCSPFailOpenFalse,
  1154  			},
  1155  			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=false&validateDefaultParameters=true",
  1156  		},
  1157  		{
  1158  			cfg: &Config{
  1159  				User:                      "u",
  1160  				Password:                  "p",
  1161  				Account:                   "a",
  1162  				ValidateDefaultParameters: ConfigBoolFalse,
  1163  			},
  1164  			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=true&validateDefaultParameters=false",
  1165  		},
  1166  		{
  1167  			cfg: &Config{
  1168  				User:                      "u",
  1169  				Password:                  "p",
  1170  				Account:                   "a",
  1171  				ValidateDefaultParameters: ConfigBoolTrue,
  1172  			},
  1173  			dsn: "u:p@a.snowflakecomputing.com:443?ocspFailOpen=true&validateDefaultParameters=true",
  1174  		},
  1175  		{
  1176  			cfg: &Config{
  1177  				User:         "u",
  1178  				Password:     "p",
  1179  				Account:      "a",
  1180  				InsecureMode: true,
  1181  			},
  1182  			dsn: "u:p@a.snowflakecomputing.com:443?insecureMode=true&ocspFailOpen=true&validateDefaultParameters=true",
  1183  		},
  1184  		{
  1185  			cfg: &Config{
  1186  				User:     "u",
  1187  				Password: "p",
  1188  				Account:  "a.b.c",
  1189  			},
  1190  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1191  		},
  1192  		{
  1193  			cfg: &Config{
  1194  				User:     "u",
  1195  				Password: "p",
  1196  				Account:  "a.b.c",
  1197  				Region:   "us-west-2",
  1198  			},
  1199  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1200  		},
  1201  		{
  1202  			cfg: &Config{
  1203  				User:     "u",
  1204  				Password: "p",
  1205  				Account:  "a.b.c",
  1206  				Region:   "r",
  1207  			},
  1208  			err: errInvalidRegion(),
  1209  		},
  1210  		{
  1211  			cfg: &Config{
  1212  				User:             "u",
  1213  				Password:         "p",
  1214  				Account:          "a.b.c",
  1215  				ClientTimeout:    400 * time.Second,
  1216  				JWTClientTimeout: 60 * time.Second,
  1217  			},
  1218  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?clientTimeout=400&jwtClientTimeout=60&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1219  		},
  1220  		{
  1221  			cfg: &Config{
  1222  				User:             "u",
  1223  				Password:         "p",
  1224  				Account:          "a.b.c",
  1225  				ClientTimeout:    400 * time.Second,
  1226  				JWTExpireTimeout: 30 * time.Second,
  1227  			},
  1228  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?clientTimeout=400&jwtTimeout=30&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1229  		},
  1230  		{
  1231  			cfg: &Config{
  1232  				User:     "u",
  1233  				Password: "p",
  1234  				Account:  "a.b.c",
  1235  				Protocol: "http",
  1236  			},
  1237  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?ocspFailOpen=true&protocol=http&region=b.c&validateDefaultParameters=true",
  1238  		},
  1239  		{
  1240  			cfg: &Config{
  1241  				User:     "u",
  1242  				Password: "p",
  1243  				Account:  "a.b.c",
  1244  				Tracing:  "debug",
  1245  			},
  1246  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?ocspFailOpen=true&region=b.c&tracing=debug&validateDefaultParameters=true",
  1247  		},
  1248  		{
  1249  			cfg: &Config{
  1250  				User:                  "u",
  1251  				Password:              "p",
  1252  				Account:               "a.b.c",
  1253  				Authenticator:         AuthTypeUsernamePasswordMFA,
  1254  				ClientRequestMfaToken: ConfigBoolTrue,
  1255  			},
  1256  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?authenticator=username_password_mfa&clientRequestMfaToken=true&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1257  		},
  1258  		{
  1259  			cfg: &Config{
  1260  				User:                  "u",
  1261  				Password:              "p",
  1262  				Account:               "a.b.c",
  1263  				Authenticator:         AuthTypeUsernamePasswordMFA,
  1264  				ClientRequestMfaToken: ConfigBoolFalse,
  1265  			},
  1266  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?authenticator=username_password_mfa&clientRequestMfaToken=false&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1267  		},
  1268  		{
  1269  			cfg: &Config{
  1270  				User:      "u",
  1271  				Password:  "p",
  1272  				Account:   "a.b.c",
  1273  				Warehouse: "wh",
  1274  			},
  1275  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?ocspFailOpen=true&region=b.c&validateDefaultParameters=true&warehouse=wh",
  1276  		},
  1277  		{
  1278  			cfg: &Config{
  1279  				User:     "u",
  1280  				Password: "p",
  1281  				Account:  "a.b.c",
  1282  				Token:    "t",
  1283  			},
  1284  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?ocspFailOpen=true&region=b.c&token=t&validateDefaultParameters=true",
  1285  		},
  1286  		{
  1287  			cfg: &Config{
  1288  				User:          "u",
  1289  				Password:      "p",
  1290  				Account:       "a.b.c",
  1291  				Authenticator: AuthTypeTokenAccessor,
  1292  			},
  1293  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?authenticator=tokenaccessor&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1294  		},
  1295  		{
  1296  			cfg: &Config{
  1297  				User:       "u",
  1298  				Password:   "p",
  1299  				Account:    "a.b.c",
  1300  				TmpDirPath: "/tmp",
  1301  			},
  1302  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?ocspFailOpen=true&region=b.c&tmpDirPath=%2Ftmp&validateDefaultParameters=true",
  1303  		},
  1304  		{
  1305  			cfg: &Config{
  1306  				User:               "u",
  1307  				Password:           "p",
  1308  				Account:            "a.b.c",
  1309  				IncludeRetryReason: ConfigBoolFalse,
  1310  				MaxRetryCount:      30,
  1311  			},
  1312  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?includeRetryReason=false&maxRetryCount=30&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1313  		},
  1314  		{
  1315  			cfg: &Config{
  1316  				User:                     "u",
  1317  				Password:                 "p",
  1318  				Account:                  "a.b.c",
  1319  				DisableQueryContextCache: true,
  1320  				IncludeRetryReason:       ConfigBoolTrue,
  1321  			},
  1322  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?disableQueryContextCache=true&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1323  		},
  1324  		{
  1325  			cfg: &Config{
  1326  				User:               "u",
  1327  				Password:           "p",
  1328  				Account:            "a.b.c",
  1329  				IncludeRetryReason: ConfigBoolFalse,
  1330  			},
  1331  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?includeRetryReason=false&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1332  		},
  1333  		{
  1334  			cfg: &Config{
  1335  				User:               "u",
  1336  				Password:           "p",
  1337  				Account:            "a.b.c",
  1338  				IncludeRetryReason: ConfigBoolTrue,
  1339  			},
  1340  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1341  		},
  1342  		{
  1343  			cfg: &Config{
  1344  				User:               "u",
  1345  				Password:           "p",
  1346  				Account:            "a.b.c",
  1347  				IncludeRetryReason: ConfigBoolTrue,
  1348  				ClientConfigFile:   "/Users/user/config.json",
  1349  			},
  1350  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?clientConfigFile=%2FUsers%2Fuser%2Fconfig.json&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1351  		},
  1352  		{
  1353  			cfg: &Config{
  1354  				User:               "u",
  1355  				Password:           "p",
  1356  				Account:            "a.b.c",
  1357  				IncludeRetryReason: ConfigBoolTrue,
  1358  				ClientConfigFile:   "c:\\Users\\user\\config.json",
  1359  			},
  1360  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?clientConfigFile=c%3A%5CUsers%5Cuser%5Cconfig.json&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1361  		},
  1362  		{
  1363  			cfg: &Config{
  1364  				User:                "u",
  1365  				Password:            "p",
  1366  				Account:             "a.b.c",
  1367  				Authenticator:       AuthTypeExternalBrowser,
  1368  				DisableConsoleLogin: ConfigBoolTrue,
  1369  			},
  1370  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?authenticator=externalbrowser&disableConsoleLogin=true&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1371  		},
  1372  		{
  1373  			cfg: &Config{
  1374  				User:                "u",
  1375  				Password:            "p",
  1376  				Account:             "a.b.c",
  1377  				Authenticator:       AuthTypeExternalBrowser,
  1378  				DisableConsoleLogin: ConfigBoolFalse,
  1379  			},
  1380  			dsn: "u:p@a.b.c.snowflakecomputing.com:443?authenticator=externalbrowser&disableConsoleLogin=false&ocspFailOpen=true&region=b.c&validateDefaultParameters=true",
  1381  		},
  1382  	}
  1383  	for _, test := range testcases {
  1384  		t.Run(test.dsn, func(t *testing.T) {
  1385  			dsn, err := DSN(test.cfg)
  1386  			if test.err == nil && err == nil {
  1387  				if dsn != test.dsn {
  1388  					t.Errorf("failed to get DSN. expected: %v, got:\n %v", test.dsn, dsn)
  1389  				}
  1390  				_, err := ParseDSN(dsn)
  1391  				if err != nil {
  1392  					t.Errorf("failed to parse DSN. dsn: %v, err: %v", dsn, err)
  1393  				}
  1394  			}
  1395  			if test.err != nil && err == nil {
  1396  				t.Errorf("expected error. dsn: %v, err: %v", test.dsn, test.err)
  1397  			}
  1398  			if err != nil && test.err == nil {
  1399  				t.Errorf("failed to match. err: %v", err)
  1400  			}
  1401  		})
  1402  	}
  1403  }
  1404  
  1405  func TestParsePrivateKeyFromFileMissingFile(t *testing.T) {
  1406  	_, err := parsePrivateKeyFromFile("nonexistent")
  1407  
  1408  	if err == nil {
  1409  		t.Error("should report error for nonexistent file")
  1410  	}
  1411  }
  1412  
  1413  func TestParsePrivateKeyFromFileIncorrectData(t *testing.T) {
  1414  	pemFile := createTmpFile("exampleKey.pem", []byte("gibberish"))
  1415  	_, err := parsePrivateKeyFromFile(pemFile)
  1416  
  1417  	if err == nil {
  1418  		t.Error("should report error for wrong data in file")
  1419  	}
  1420  }
  1421  
  1422  func TestParsePrivateKeyFromFileNotRSAPrivateKey(t *testing.T) {
  1423  	// Generate an ECDSA private key for testing
  1424  	ecdsaPrivateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  1425  	if err != nil {
  1426  		t.Fatalf("failed to generate ECDSA private key: %v", err)
  1427  	}
  1428  
  1429  	ecdsaPrivateKeyBytes, err := x509.MarshalECPrivateKey(ecdsaPrivateKey)
  1430  	if err != nil {
  1431  		t.Fatalf("failed to marshal ECDSA private key: %v", err)
  1432  	}
  1433  	pemBlock := &pem.Block{
  1434  		Type:  "EC PRIVATE KEY",
  1435  		Bytes: ecdsaPrivateKeyBytes,
  1436  	}
  1437  	pemData := pem.EncodeToMemory(pemBlock)
  1438  
  1439  	// Write the PEM data to a temporary file
  1440  	pemFile := createTmpFile("ecdsaKey.pem", pemData)
  1441  
  1442  	// Attempt to parse the private key
  1443  	_, err = parsePrivateKeyFromFile(pemFile)
  1444  	if err == nil {
  1445  		t.Error("expected an error when trying to parse an ECDSA private key as RSA")
  1446  	}
  1447  }
  1448  
  1449  func TestParsePrivateKeyFromFile(t *testing.T) {
  1450  	generatedKey, _ := rsa.GenerateKey(cr.Reader, 1024)
  1451  	pemKey, _ := x509.MarshalPKCS8PrivateKey(generatedKey)
  1452  	pemData := pem.EncodeToMemory(
  1453  		&pem.Block{
  1454  			Type:  "RSA PRIVATE KEY",
  1455  			Bytes: pemKey,
  1456  		},
  1457  	)
  1458  	keyFile := createTmpFile("exampleKey.pem", pemData)
  1459  	defer os.Remove(keyFile)
  1460  
  1461  	parsedKey, err := parsePrivateKeyFromFile(keyFile)
  1462  	if err != nil {
  1463  		t.Errorf("unable to parse pam file from path: %v, err: %v", keyFile, err)
  1464  	} else if !parsedKey.Equal(generatedKey) {
  1465  		t.Errorf("generated key does not equal to parsed key from file\ngeneratedKey=%v\nparsedKey=%v",
  1466  			generatedKey, parsedKey)
  1467  	}
  1468  }
  1469  
  1470  func createTmpFile(fileName string, content []byte) string {
  1471  	tempFile, _ := os.CreateTemp("", fileName)
  1472  	tempFile.Write(content)
  1473  	absolutePath := tempFile.Name()
  1474  	return absolutePath
  1475  }
  1476  
  1477  type configParamToValue struct {
  1478  	configParam string
  1479  	value       string
  1480  }
  1481  
  1482  func TestGetConfigFromEnv(t *testing.T) {
  1483  	envMap := map[string]configParamToValue{
  1484  		"SF_TEST_ACCOUNT":     {"Account", "account"},
  1485  		"SF_TEST_USER":        {"User", "user"},
  1486  		"SF_TEST_PASSWORD":    {"Password", "password"},
  1487  		"SF_TEST_ROLE":        {"Role", "role"},
  1488  		"SF_TEST_HOST":        {"Host", "host"},
  1489  		"SF_TEST_PORT":        {"Port", "8080"},
  1490  		"SF_TEST_PROTOCOL":    {"Protocol", "http"},
  1491  		"SF_TEST_WAREHOUSE":   {"Warehouse", "warehouse"},
  1492  		"SF_TEST_DATABASE":    {"Database", "database"},
  1493  		"SF_TEST_REGION":      {"Region", "region"},
  1494  		"SF_TEST_PASSCODE":    {"Passcode", "passcode"},
  1495  		"SF_TEST_SCHEMA":      {"Schema", "schema"},
  1496  		"SF_TEST_APPLICATION": {"Application", "application"},
  1497  	}
  1498  	var properties = make([]*ConfigParam, len(envMap))
  1499  	i := 0
  1500  	for key, ctv := range envMap {
  1501  		os.Setenv(key, ctv.value)
  1502  		cfgParam := ConfigParam{ctv.configParam, key, true}
  1503  		properties[i] = &cfgParam
  1504  		i++
  1505  	}
  1506  	defer func() {
  1507  		for key := range envMap {
  1508  			os.Unsetenv(key)
  1509  		}
  1510  	}()
  1511  
  1512  	cfg, err := GetConfigFromEnv(properties)
  1513  	if err != nil {
  1514  		t.Errorf("unable to parse env variables to Config, err: %v", err)
  1515  	}
  1516  
  1517  	err = checkConfig(*cfg, envMap)
  1518  	if err != nil {
  1519  		t.Error(err)
  1520  	}
  1521  }
  1522  
  1523  func checkConfig(cfg Config, envMap map[string]configParamToValue) error {
  1524  	appendError := func(errArray []string, envName string, expected string, received string) []string {
  1525  		errArray = append(errArray, fmt.Sprintf("field %v expected value: %v, received value: %v", envName, expected, received))
  1526  		return errArray
  1527  	}
  1528  
  1529  	value := reflect.ValueOf(cfg)
  1530  	typeOfCfg := value.Type()
  1531  	cfgValues := make(map[string]interface{}, value.NumField())
  1532  	for i := 0; i < value.NumField(); i++ {
  1533  		cfgValues[typeOfCfg.Field(i).Name] = value.Field(i).Interface()
  1534  	}
  1535  
  1536  	var errArray []string
  1537  	for key, ctv := range envMap {
  1538  		if ctv.configParam == "Port" {
  1539  			if portStr := strconv.Itoa(cfgValues[ctv.configParam].(int)); portStr != ctv.value {
  1540  				errArray = appendError(errArray, key, ctv.value, cfgValues[ctv.configParam].(string))
  1541  			}
  1542  		} else if cfgValues[ctv.configParam] != ctv.value {
  1543  			errArray = appendError(errArray, key, ctv.value, cfgValues[ctv.configParam].(string))
  1544  		}
  1545  	}
  1546  
  1547  	if errArray != nil {
  1548  		return fmt.Errorf(strings.Join(errArray, "\n"))
  1549  	}
  1550  
  1551  	return nil
  1552  }
  1553  
  1554  func TestConfigValidateTmpDirPath(t *testing.T) {
  1555  	cfg := &Config{
  1556  		TmpDirPath: "/not/existing",
  1557  	}
  1558  	if err := cfg.Validate(); err == nil {
  1559  		t.Fatalf("Should fail on not existing TmpDirPath")
  1560  	}
  1561  }