go.temporal.io/server@v1.23.0/common/persistence/sql/sqlplugin/mysql/session/session_test.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2020 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2020 Uber Technologies, Inc.
     6  //
     7  // Permission is hereby granted, free of charge, to any person obtaining a copy
     8  // of this software and associated documentation files (the "Software"), to deal
     9  // in the Software without restriction, including without limitation the rights
    10  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11  // copies of the Software, and to permit persons to whom the Software is
    12  // furnished to do so, subject to the following conditions:
    13  //
    14  // The above copyright notice and this permission notice shall be included in
    15  // all copies or substantial portions of the Software.
    16  //
    17  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23  // THE SOFTWARE.
    24  
    25  package session
    26  
    27  import (
    28  	"net/url"
    29  	"strings"
    30  	"testing"
    31  
    32  	"github.com/golang/mock/gomock"
    33  	"github.com/stretchr/testify/suite"
    34  
    35  	"go.temporal.io/server/common/config"
    36  	"go.temporal.io/server/common/resolver"
    37  )
    38  
    39  type (
    40  	sessionTestSuite struct {
    41  		suite.Suite
    42  		controller *gomock.Controller
    43  	}
    44  )
    45  
    46  func TestSessionTestSuite(t *testing.T) {
    47  	s := new(sessionTestSuite)
    48  	suite.Run(t, s)
    49  }
    50  
    51  func (s *sessionTestSuite) SetupSuite() {
    52  
    53  }
    54  
    55  func (s *sessionTestSuite) TearDownSuite() {
    56  
    57  }
    58  
    59  func (s *sessionTestSuite) SetupTest() {
    60  	s.controller = gomock.NewController(s.T())
    61  }
    62  
    63  func (s *sessionTestSuite) TearDownTest() {
    64  	s.controller.Finish()
    65  }
    66  
    67  func (s *sessionTestSuite) TestBuildDSN() {
    68  	testCases := []struct {
    69  		in              config.SQL
    70  		outURLPath      string
    71  		outIsolationKey string
    72  		outIsolationVal string
    73  	}{
    74  		{
    75  			in: config.SQL{
    76  				User:            "test",
    77  				Password:        "pass",
    78  				ConnectProtocol: "tcp",
    79  				ConnectAddr:     "192.168.0.1:3306",
    80  				DatabaseName:    "db1",
    81  			},
    82  			outIsolationKey: "transaction_isolation",
    83  			outIsolationVal: "'READ-COMMITTED'",
    84  			outURLPath:      "test:pass@tcp(192.168.0.1:3306)/db1?",
    85  		},
    86  		{
    87  			in: config.SQL{
    88  				User:              "test",
    89  				Password:          "pass",
    90  				ConnectProtocol:   "tcp",
    91  				ConnectAddr:       "192.168.0.1:3306",
    92  				DatabaseName:      "db1",
    93  				ConnectAttributes: map[string]string{"k1": "v1", "k2": "v2"},
    94  			},
    95  			outIsolationKey: "transaction_isolation",
    96  			outIsolationVal: "'READ-COMMITTED'",
    97  			outURLPath:      "test:pass@tcp(192.168.0.1:3306)/db1?",
    98  		},
    99  		{
   100  			in: config.SQL{
   101  				User:              "test",
   102  				Password:          "pass",
   103  				ConnectProtocol:   "tcp",
   104  				ConnectAddr:       "192.168.0.1:3306",
   105  				DatabaseName:      "db1",
   106  				ConnectAttributes: map[string]string{"k1": "v1", "k2": "v2", "tx_isolation": "'REPEATABLE-READ'"},
   107  			},
   108  			outIsolationKey: "tx_isolation",
   109  			outIsolationVal: "'repeatable-read'",
   110  			outURLPath:      "test:pass@tcp(192.168.0.1:3306)/db1?",
   111  		},
   112  		{
   113  			in: config.SQL{
   114  				User:              "test",
   115  				Password:          "pass",
   116  				ConnectProtocol:   "tcp",
   117  				ConnectAddr:       "192.168.0.1:3306",
   118  				DatabaseName:      "db1",
   119  				ConnectAttributes: map[string]string{"k1": "v1", "k2": "v2", "tx_isolation": "REPEATABLE-READ"},
   120  			},
   121  			outIsolationKey: "tx_isolation",
   122  			outIsolationVal: "'repeatable-read'",
   123  			outURLPath:      "test:pass@tcp(192.168.0.1:3306)/db1?",
   124  		},
   125  		{
   126  			in: config.SQL{
   127  				User:              "test",
   128  				Password:          "pass",
   129  				ConnectProtocol:   "tcp",
   130  				ConnectAddr:       "192.168.0.1:3306",
   131  				DatabaseName:      "db1",
   132  				ConnectAttributes: map[string]string{"k1": "v1", "k2": "v2", "transaction_isolation": "REPEATABLE-READ"},
   133  			},
   134  			outIsolationKey: "transaction_isolation",
   135  			outIsolationVal: "'repeatable-read'",
   136  			outURLPath:      "test:pass@tcp(192.168.0.1:3306)/db1?",
   137  		},
   138  	}
   139  
   140  	for _, tc := range testCases {
   141  		r := resolver.NewMockServiceResolver(s.controller)
   142  		r.EXPECT().Resolve(tc.in.ConnectAddr).Return([]string{tc.in.ConnectAddr})
   143  
   144  		out := buildDSN(&tc.in, r)
   145  		s.True(strings.HasPrefix(out, tc.outURLPath), "invalid url path")
   146  		tokens := strings.Split(out, "?")
   147  		s.Equal(2, len(tokens), "invalid url")
   148  		qry, err := url.Parse("?" + tokens[1])
   149  		s.NoError(err)
   150  		wantAttrs := buildExpectedURLParams(tc.in.ConnectAttributes, tc.outIsolationKey, tc.outIsolationVal)
   151  		s.Equal(wantAttrs, qry.Query(), "invalid dsn url params")
   152  	}
   153  }
   154  
   155  func buildExpectedURLParams(attrs map[string]string, isolationKey string, isolationValue string) url.Values {
   156  	result := make(map[string][]string, len(dsnAttrOverrides)+len(attrs)+1)
   157  	for k, v := range attrs {
   158  		result[k] = []string{v}
   159  	}
   160  	result[isolationKey] = []string{isolationValue}
   161  	for k, v := range dsnAttrOverrides {
   162  		result[k] = []string{v}
   163  	}
   164  	result["rejectReadOnly"] = []string{"true"}
   165  	return result
   166  }