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  }