go.temporal.io/server@v1.23.0/common/persistence/tests/mysql_test_util.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 tests 26 27 import ( 28 "fmt" 29 "net" 30 "path/filepath" 31 "strconv" 32 "testing" 33 34 "go.uber.org/zap/zaptest" 35 36 "go.temporal.io/server/common/config" 37 "go.temporal.io/server/common/log" 38 p "go.temporal.io/server/common/persistence" 39 "go.temporal.io/server/common/persistence/sql" 40 "go.temporal.io/server/common/persistence/sql/sqlplugin" 41 "go.temporal.io/server/common/persistence/sql/sqlplugin/mysql" 42 "go.temporal.io/server/common/resolver" 43 "go.temporal.io/server/common/shuffle" 44 "go.temporal.io/server/environment" 45 ) 46 47 // TODO merge the initialization with existing persistence setup 48 const ( 49 testMySQLClusterName = "temporal_mysql_cluster" 50 51 testMySQLUser = "temporal" 52 testMySQLPassword = "temporal" 53 testMySQLConnectionProtocol = "tcp" 54 testMySQLDatabaseNamePrefix = "test_" 55 testMySQLDatabaseNameSuffix = "temporal_persistence" 56 57 // TODO hard code this dir for now 58 // need to merge persistence test config / initialization in one place 59 testMySQLExecutionSchema = "../../../schema/mysql/v8/temporal/schema.sql" 60 testMySQLVisibilitySchema = "../../../schema/mysql/v8/visibility/schema.sql" 61 ) 62 63 type ( 64 MySQLTestData struct { 65 Cfg *config.SQL 66 Factory *sql.Factory 67 Logger log.Logger 68 } 69 ) 70 71 func setUpMySQLTest(t *testing.T) (MySQLTestData, func()) { 72 var testData MySQLTestData 73 testData.Cfg = NewMySQLConfig() 74 testData.Logger = log.NewZapLogger(zaptest.NewLogger(t)) 75 SetupMySQLDatabase(testData.Cfg) 76 SetupMySQLSchema(testData.Cfg) 77 78 testData.Factory = sql.NewFactory( 79 *testData.Cfg, 80 resolver.NewNoopResolver(), 81 testMySQLClusterName, 82 testData.Logger, 83 ) 84 85 tearDown := func() { 86 testData.Factory.Close() 87 TearDownMySQLDatabase(testData.Cfg) 88 } 89 90 return testData, tearDown 91 } 92 93 // NewMySQLConfig returns a new MySQL config for test 94 func NewMySQLConfig() *config.SQL { 95 return &config.SQL{ 96 User: testMySQLUser, 97 Password: testMySQLPassword, 98 ConnectAddr: net.JoinHostPort( 99 environment.GetMySQLAddress(), 100 strconv.Itoa(environment.GetMySQLPort()), 101 ), 102 ConnectProtocol: testMySQLConnectionProtocol, 103 PluginName: mysql.PluginNameV8, 104 DatabaseName: testMySQLDatabaseNamePrefix + shuffle.String(testMySQLDatabaseNameSuffix), 105 } 106 } 107 108 func SetupMySQLDatabase(cfg *config.SQL) { 109 adminCfg := *cfg 110 // NOTE need to connect with empty name to create new database 111 adminCfg.DatabaseName = "" 112 113 db, err := sql.NewSQLAdminDB(sqlplugin.DbKindUnknown, &adminCfg, resolver.NewNoopResolver()) 114 if err != nil { 115 panic(fmt.Sprintf("unable to create MySQL admin DB: %v", err)) 116 } 117 defer func() { _ = db.Close() }() 118 119 err = db.CreateDatabase(cfg.DatabaseName) 120 if err != nil { 121 panic(fmt.Sprintf("unable to create MySQL database: %v", err)) 122 } 123 } 124 125 func SetupMySQLSchema(cfg *config.SQL) { 126 db, err := sql.NewSQLAdminDB(sqlplugin.DbKindUnknown, cfg, resolver.NewNoopResolver()) 127 if err != nil { 128 panic(fmt.Sprintf("unable to create MySQL admin DB: %v", err)) 129 } 130 defer func() { _ = db.Close() }() 131 132 schemaPath, err := filepath.Abs(testMySQLExecutionSchema) 133 if err != nil { 134 panic(err) 135 } 136 137 statements, err := p.LoadAndSplitQuery([]string{schemaPath}) 138 if err != nil { 139 panic(err) 140 } 141 142 for _, stmt := range statements { 143 if err = db.Exec(stmt); err != nil { 144 panic(err) 145 } 146 } 147 148 schemaPath, err = filepath.Abs(testMySQLVisibilitySchema) 149 if err != nil { 150 panic(err) 151 } 152 153 statements, err = p.LoadAndSplitQuery([]string{schemaPath}) 154 if err != nil { 155 panic(err) 156 } 157 158 for _, stmt := range statements { 159 if err = db.Exec(stmt); err != nil { 160 panic(err) 161 } 162 } 163 } 164 165 func TearDownMySQLDatabase(cfg *config.SQL) { 166 adminCfg := *cfg 167 // NOTE need to connect with empty name to create new database 168 adminCfg.DatabaseName = "" 169 170 db, err := sql.NewSQLAdminDB(sqlplugin.DbKindUnknown, &adminCfg, resolver.NewNoopResolver()) 171 if err != nil { 172 panic(fmt.Sprintf("unable to create MySQL admin DB: %v", err)) 173 } 174 defer func() { _ = db.Close() }() 175 176 err = db.DropDatabase(cfg.DatabaseName) 177 if err != nil { 178 panic(fmt.Sprintf("unable to drop MySQL database: %v", err)) 179 } 180 }