@@ -25,16 +25,19 @@ package test
2525import (
2626 "context"
2727 "crypto/tls"
28+ "fmt"
2829 "log"
2930 httplib "net/http"
3031 _ "net/http/pprof"
3132 "os"
33+ "runtime"
3234 "strconv"
3335 "strings"
3436 "sync"
3537 "testing"
3638 "time"
3739
40+ "github.com/pkg/errors"
3841 "github.com/stretchr/testify/assert"
3942 "github.com/stretchr/testify/require"
4043
@@ -500,3 +503,95 @@ func TestCreateClientHttpRepeatConnection(t *testing.T) {
500503 require .NoError (t , err )
501504 assert .Equal (t , 2 , requestRepeat .counter )
502505}
506+
507+ // TestClientConnectionReuse checks that reusing same connection with different auth parameters is possible using
508+ func TestClientConnectionReuse (t * testing.T ) {
509+ if os .Getenv ("TEST_CONNECTION" ) == "vst" {
510+ t .Skip ("not possible with VST connections by design" )
511+ return
512+ }
513+
514+ c := createClientFromEnv (t , true )
515+ ctx := context .Background ()
516+
517+ prefix := t .Name ()
518+ dbUsers := map [string ]driver.CreateDatabaseUserOptions {
519+ prefix + "-db1" : {UserName : prefix + "-user1" , Password : "password1" },
520+ prefix + "-db2" : {UserName : prefix + "-user2" , Password : "password2" },
521+ }
522+ for dbName , userOptions := range dbUsers {
523+ ensureDatabase (ctx , c , dbName , & driver.CreateDatabaseOptions {
524+ Users : []driver.CreateDatabaseUserOptions {userOptions },
525+ Options : driver.CreateDatabaseDefaultOptions {},
526+ }, t )
527+ }
528+
529+ var wg sync.WaitGroup
530+ const clientsPerDB = 20
531+ startTime := time .Now ()
532+
533+ const testDuration = time .Second * 10
534+ if testing .Verbose () {
535+ wg .Add (1 )
536+ go func () {
537+ defer wg .Done ()
538+
539+ for {
540+ stats , _ := c .Statistics (ctx )
541+ t .Logf ("goroutine count: %d, server connections: %d" , runtime .NumGoroutine (), stats .Client .HTTPConnections )
542+ if time .Now ().Sub (startTime ) > testDuration {
543+ break
544+ }
545+ time .Sleep (1 * time .Second )
546+ }
547+ }()
548+ }
549+
550+ conn := createConnection (t , false )
551+ for dbName , userOptions := range dbUsers {
552+ t .Logf ("Starting %d goroutines for DB %s ..." , clientsPerDB , dbName )
553+ for i := 0 ; i < clientsPerDB ; i ++ {
554+ wg .Add (1 )
555+ go func (dbName string , userOptions driver.CreateDatabaseUserOptions , conn driver.Connection ) {
556+ defer wg .Done ()
557+ for {
558+ if time .Now ().Sub (startTime ) > testDuration {
559+ break
560+ }
561+
562+ // the test will pass only if checkDBAccess is using mutex
563+ err := checkDBAccess (ctx , conn , dbName , userOptions .UserName , userOptions .Password )
564+ require .NoError (t , err )
565+
566+ time .Sleep (10 * time .Millisecond )
567+ }
568+ }(dbName , userOptions , conn )
569+ }
570+ }
571+ wg .Wait ()
572+ }
573+
574+ func checkDBAccess (ctx context.Context , conn driver.Connection , dbName , username , password string ) error {
575+ client , err := driver .NewClient (driver.ClientConfig {
576+ Connection : conn ,
577+ Authentication : driver .BasicAuthentication (username , password ),
578+ })
579+ if err != nil {
580+ return err
581+ }
582+
583+ dbExists , err := client .DatabaseExists (ctx , dbName )
584+ if err != nil {
585+ return errors .Wrapf (err , "DatabaseExists failed" )
586+ }
587+ if ! dbExists {
588+ return fmt .Errorf ("db %s must exist for any user" , dbName )
589+ }
590+
591+ _ , err = client .Database (ctx , dbName )
592+ if err != nil {
593+ return errors .Wrapf (err , "db %s must be accessible for user %s" , dbName , username )
594+ }
595+
596+ return nil
597+ }
0 commit comments