github.com/SaurabhDubey-Groww/go-cloud@v0.0.0-20221124105541-b26c29285fd8/mysql/gcpmysql/gcpmysql_test.go (about) 1 // Copyright 2018 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package gcpmysql 16 17 import ( 18 "context" 19 "fmt" 20 "net/url" 21 "reflect" 22 "testing" 23 24 drvr "github.com/go-sql-driver/mysql" 25 "gocloud.dev/internal/testing/terraform" 26 "gocloud.dev/mysql" 27 ) 28 29 func TestOpen(t *testing.T) { 30 // This test will be skipped unless the project is set up with Terraform. 31 // Before running go test, run in this directory: 32 // 33 // terraform init 34 // terraform apply 35 36 tfOut, err := terraform.ReadOutput(".") 37 if err != nil || len(tfOut) == 0 { 38 t.Skipf("Could not obtain harness info: %v", err) 39 } 40 project, _ := tfOut["project"].Value.(string) 41 region, _ := tfOut["region"].Value.(string) 42 instance, _ := tfOut["instance"].Value.(string) 43 username, _ := tfOut["username"].Value.(string) 44 password, _ := tfOut["password"].Value.(string) 45 databaseName, _ := tfOut["database"].Value.(string) 46 if project == "" || region == "" || instance == "" || username == "" || databaseName == "" { 47 t.Fatalf("Missing one or more required Terraform outputs; got project=%q region=%q instance=%q username=%q database=%q", project, region, instance, username, databaseName) 48 } 49 50 ctx := context.Background() 51 urlstr := fmt.Sprintf("gcpmysql://%s:%s@%s/%s/%s/%s", username, password, project, region, instance, databaseName) 52 t.Log("Connecting to", urlstr) 53 db, err := mysql.Open(ctx, urlstr) 54 if err != nil { 55 t.Fatal(err) 56 } 57 if err := db.Ping(); err != nil { 58 t.Error("Ping:", err) 59 } 60 if err := db.Close(); err != nil { 61 t.Error("Close:", err) 62 } 63 } 64 65 func TestInstanceFromURL(t *testing.T) { 66 tests := []struct { 67 name string 68 urlString string 69 wantInstance string 70 wantDatabase string 71 wantErr bool 72 }{ 73 { 74 name: "AllValuesSpecified", 75 urlString: "gcpmysql://username:password@my-project-id/us-central1/my-instance-id/my-db?foo=bar&baz=quux", 76 wantInstance: "my-project-id:us-central1:my-instance-id", 77 wantDatabase: "my-db", 78 }, 79 { 80 name: "OptionalValuesOmitted", 81 urlString: "gcpmysql://my-project-id/us-central1/my-instance-id/my-db", 82 wantInstance: "my-project-id:us-central1:my-instance-id", 83 wantDatabase: "my-db", 84 }, 85 { 86 name: "DatabaseNameEmpty", 87 urlString: "gcpmysql://my-project-id/us-central1/my-instance-id/", 88 wantErr: true, 89 }, 90 { 91 name: "InstanceEmpty", 92 urlString: "gcpmysql://my-project-id/us-central1//my-db", 93 wantErr: true, 94 }, 95 { 96 name: "RegionEmpty", 97 urlString: "gcpmysql://my-project-id//my-instance-id/my-db", 98 wantErr: true, 99 }, 100 { 101 name: "ProjectEmpty", 102 urlString: "gcpmysql:///us-central1/my-instance-id/my-db", 103 wantErr: true, 104 }, 105 { 106 name: "DatabaseNameWithSlashes", 107 urlString: "gcpmysql://my-project-id/us-central1/my-instance-id/foo/bar/baz", 108 wantInstance: "my-project-id:us-central1:my-instance-id", 109 wantDatabase: "foo/bar/baz", 110 }, 111 } 112 for _, test := range tests { 113 t.Run(test.name, func(t *testing.T) { 114 u, err := url.Parse(test.urlString) 115 if err != nil { 116 t.Fatalf("failed to parse URL %q: %v", test.urlString, err) 117 } 118 instance, database, err := instanceFromURL(u) 119 if err != nil { 120 t.Logf("instanceFromURL(url.Parse(%q)): %v", u, err) 121 if !test.wantErr { 122 t.Fail() 123 } 124 return 125 } 126 if test.wantErr { 127 t.Fatalf("instanceFromURL(url.Parse(%q)) = %q, %q, <nil>; want error", test.urlString, instance, database) 128 } 129 if instance != test.wantInstance || database != test.wantDatabase { 130 t.Errorf("instanceFromURL(url.Parse(%q)) = %q, %q, <nil>; want %q, %q, <nil>", test.urlString, instance, database, test.wantInstance, test.wantDatabase) 131 } 132 }) 133 } 134 } 135 136 func Test_configFromURL(t *testing.T) { 137 type args struct { 138 urlStr string 139 dialerName string 140 } 141 tests := []struct { 142 name string 143 args args 144 want *drvr.Config 145 wantErr bool 146 }{ 147 { 148 name: "ConfigWithNoOptions", 149 args: args{ 150 urlStr: "gcpmysql://user:password@my-project-id/us-central1/my-instance-id/my-db", 151 dialerName: "gocloud.dev/mysql/gcpmysql/1", 152 }, 153 want: func() *drvr.Config { 154 cfg := drvr.NewConfig() 155 cfg.AllowNativePasswords = true 156 cfg.Net = "gocloud.dev/mysql/gcpmysql/1" 157 cfg.Addr = "my-project-id:us-central1:my-instance-id" 158 cfg.User = "user" 159 cfg.Passwd = "password" 160 cfg.DBName = "my-db" 161 return cfg 162 }(), 163 wantErr: false, 164 }, 165 { 166 name: "ConfigWithSignalOptions", 167 args: args{ 168 urlStr: "gcpmysql://user:password@my-project-id/us-central1/my-instance-id/my-db?parseTime=true", 169 dialerName: "gocloud.dev/mysql/gcpmysql/1", 170 }, 171 want: func() *drvr.Config { 172 cfg := drvr.NewConfig() 173 cfg.AllowNativePasswords = true 174 cfg.ParseTime = true 175 cfg.Net = "gocloud.dev/mysql/gcpmysql/1" 176 cfg.Addr = "my-project-id:us-central1:my-instance-id" 177 cfg.User = "user" 178 cfg.Passwd = "password" 179 cfg.DBName = "my-db" 180 return cfg 181 }(), 182 wantErr: false, 183 }, 184 { 185 name: "ConfigWithMultipleOptions", 186 args: args{ 187 urlStr: "gcpmysql://user:password@my-project-id/us-central1/my-instance-id/my-db?columnsWithAlias=true&parseTime=true", 188 dialerName: "gocloud.dev/mysql/gcpmysql/1", 189 }, 190 want: func() *drvr.Config { 191 cfg := drvr.NewConfig() 192 cfg.AllowNativePasswords = true 193 cfg.ColumnsWithAlias = true 194 cfg.ParseTime = true 195 cfg.Net = "gocloud.dev/mysql/gcpmysql/1" 196 cfg.Addr = "my-project-id:us-central1:my-instance-id" 197 cfg.User = "user" 198 cfg.Passwd = "password" 199 cfg.DBName = "my-db" 200 return cfg 201 }(), 202 wantErr: false, 203 }, 204 { 205 name: "InstanceFromURLError", 206 args: args{ 207 urlStr: "gcpmysql://user:password@my-project-id/us-central1/my-db", 208 dialerName: "gocloud.dev/mysql/gcpmysql/1", 209 }, 210 want: nil, 211 wantErr: true, 212 }, 213 { 214 name: "DNSParseError", 215 args: args{ 216 urlStr: "gcpmysql://user:password@my-project-id/us-central1/my-instance-id/my-db?parseTime=nope", 217 dialerName: "gocloud.dev/mysql/gcpmysql/1", 218 }, 219 want: nil, 220 wantErr: true, 221 }, 222 } 223 for _, tt := range tests { 224 t.Run(tt.name, func(t *testing.T) { 225 u, err := url.Parse(tt.args.urlStr) 226 if err != nil { 227 t.Fatalf("failed to parse URL %q: %v", tt.args.urlStr, err) 228 } 229 got, err := configFromURL(u, tt.args.dialerName) 230 if (err != nil) != tt.wantErr { 231 t.Errorf("configFromURL() error = %v, wantErr %v", err, tt.wantErr) 232 return 233 } 234 if !reflect.DeepEqual(got, tt.want) { 235 t.Errorf("configFromURL() = %v, want %v", got, tt.want) 236 } 237 }) 238 } 239 }