...

Source file src/github.com/GoogleCloudPlatform/cloudsql-proxy/cmd/cloud_sql_proxy/proxy_test.go

Documentation: github.com/GoogleCloudPlatform/cloudsql-proxy/cmd/cloud_sql_proxy

     1  // Copyright 2015 Google Inc. All Rights Reserved.
     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  //      http://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 main
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"io/ioutil"
    21  	"net"
    22  	"net/http"
    23  	"os"
    24  	"runtime"
    25  	"testing"
    26  )
    27  
    28  type mockTripper struct {
    29  }
    30  
    31  func (m *mockTripper) RoundTrip(r *http.Request) (*http.Response, error) {
    32  	return &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader([]byte("{}")))}, nil
    33  }
    34  
    35  var mockClient = &http.Client{Transport: &mockTripper{}}
    36  
    37  func TestCreateInstanceConfigs(t *testing.T) {
    38  	for _, v := range []struct {
    39  		desc string
    40  		//inputs
    41  		dir          string
    42  		useFuse      bool
    43  		instances    []string
    44  		instancesSrc string
    45  
    46  		// We don't need to check the []instancesConfig return value, we already
    47  		// have a TestParseInstanceConfig.
    48  		wantErr bool
    49  
    50  		skipFailedInstanceConfig bool
    51  
    52  		supportedOnWindows bool
    53  	}{
    54  		{
    55  			"setting -fuse and -dir",
    56  			"dir", true, nil, "", false, false, false,
    57  		}, {
    58  			"setting -fuse",
    59  			"", true, nil, "", true, false, false,
    60  		}, {
    61  			"setting -fuse, -dir, and -instances",
    62  			"dir", true, []string{"proj:reg:x"}, "", true, false, false,
    63  		}, {
    64  			"setting -fuse, -dir, and -instances_metadata",
    65  			"dir", true, nil, "md", true, false, false,
    66  		}, {
    67  			"setting -dir and -instances (unix socket)",
    68  			"dir", false, []string{"proj:reg:x"}, "", false, false, false,
    69  		}, {
    70  			// tests for the case where invalid configs can still exist, when skipped
    71  			"setting -dir and -instances (unix socket) w/ something invalid",
    72  			"dir", false, []string{"proj:reg:x", "INVALID_PROJECT_STRING"}, "", false, true, false,
    73  		}, {
    74  			"Seting -instance (unix socket)",
    75  			"", false, []string{"proj:reg:x"}, "", true, false, false,
    76  		}, {
    77  			"setting -instance (tcp socket)",
    78  			"", false, []string{"proj:reg:x=tcp:1234"}, "", false, false, true,
    79  		}, {
    80  			"setting -instance (tcp socket) and -instances_metadata",
    81  			"", false, []string{"proj:reg:x=tcp:1234"}, "md", true, false, true,
    82  		}, {
    83  			"setting -dir, -instance (tcp socket), and -instances_metadata",
    84  			"dir", false, []string{"proj:reg:x=tcp:1234"}, "md", false, false, true,
    85  		}, {
    86  			"setting -dir, -instance (unix socket), and -instances_metadata",
    87  			"dir", false, []string{"proj:reg:x"}, "md", false, false, false,
    88  		}, {
    89  			"setting -dir and -instances_metadata",
    90  			"dir", false, nil, "md", false, false, false,
    91  		}, {
    92  			"setting -instances_metadata",
    93  			"", false, nil, "md", true, false, true,
    94  		},
    95  	} {
    96  		if runtime.GOOS == "windows" && !v.supportedOnWindows {
    97  			continue
    98  		}
    99  		if v.useFuse && testing.Short() {
   100  			t.Skip("skipping fuse tests in short mode.")
   101  		}
   102  		_, err := CreateInstanceConfigs(v.dir, v.useFuse, v.instances, v.instancesSrc, mockClient, v.skipFailedInstanceConfig)
   103  		if v.wantErr {
   104  			if err == nil {
   105  				t.Errorf("CreateInstanceConfigs passed when %s, wanted error", v.desc)
   106  			}
   107  			continue
   108  		}
   109  		if err != nil {
   110  			t.Errorf("CreateInstanceConfigs gave error when %s: %v", v.desc, err)
   111  		}
   112  	}
   113  }
   114  
   115  func TestParseInstanceConfig(t *testing.T) {
   116  	// sentinel values
   117  	var (
   118  		anyLoopbackAddress = "<any loopback address>"
   119  		wantErr            = instanceConfig{"<want error>", "", ""}
   120  	)
   121  
   122  	tcs := []struct {
   123  		// inputs
   124  		dir, instance string
   125  
   126  		wantCfg instanceConfig
   127  	}{
   128  		{
   129  			"/x", "domain.com:my-proj:my-reg:my-instance",
   130  			instanceConfig{"domain.com:my-proj:my-reg:my-instance", "unix", "/x/domain.com:my-proj:my-reg:my-instance"},
   131  		}, {
   132  			"/x", "my-proj:my-reg:my-instance",
   133  			instanceConfig{"my-proj:my-reg:my-instance", "unix", "/x/my-proj:my-reg:my-instance"},
   134  		}, {
   135  			"/x", "my-proj:my-reg:my-instance=unix:socket_name",
   136  			instanceConfig{"my-proj:my-reg:my-instance", "unix", "/x/socket_name"},
   137  		}, {
   138  			"/x", "my-proj:my-reg:my-instance=unix:/my/custom/sql-socket",
   139  			instanceConfig{"my-proj:my-reg:my-instance", "unix", "/my/custom/sql-socket"},
   140  		}, {
   141  			"/x", "my-proj:my-reg:my-instance=tcp:1234",
   142  			instanceConfig{"my-proj:my-reg:my-instance", "tcp", anyLoopbackAddress},
   143  		}, {
   144  			"/x", "my-proj:my-reg:my-instance=tcp4:1234",
   145  			instanceConfig{"my-proj:my-reg:my-instance", "tcp4", "127.0.0.1:1234"},
   146  		}, {
   147  			"/x", "my-proj:my-reg:my-instance=tcp6:1234",
   148  			instanceConfig{"my-proj:my-reg:my-instance", "tcp6", "[::1]:1234"},
   149  		}, {
   150  			"/x", "my-proj:my-reg:my-instance=tcp:my-host:1111",
   151  			instanceConfig{"my-proj:my-reg:my-instance", "tcp", "my-host:1111"},
   152  		}, {
   153  			"/x", "my-proj:my-reg:my-instance=",
   154  			wantErr,
   155  		}, {
   156  			"/x", "my-proj:my-reg:my-instance=cool network",
   157  			wantErr,
   158  		}, {
   159  			"/x", "my-proj:my-reg:my-instance=cool network:1234",
   160  			wantErr,
   161  		}, {
   162  			"/x", "my-proj:my-reg:my-instance=oh:so:many:colons",
   163  			wantErr,
   164  		},
   165  	}
   166  
   167  	for _, tc := range tcs {
   168  		t.Run(fmt.Sprintf("parseInstanceConfig(%q, %q)", tc.dir, tc.instance), func(t *testing.T) {
   169  			if os.Getenv("EXPECT_IPV4_AND_IPV6") != "true" {
   170  				// Skip ipv4 and ipv6 if they are not supported by the machine.
   171  				// (assumption is that validNets isn't buggy)
   172  				if tc.wantCfg.Network == "tcp4" || tc.wantCfg.Network == "tcp6" {
   173  					if !validNets[tc.wantCfg.Network] {
   174  						t.Skipf("%q net not supported, skipping", tc.wantCfg.Network)
   175  					}
   176  				}
   177  				// Skip unix sockets on Windows
   178  				if runtime.GOOS == "windows" && tc.wantCfg.Network == "unix" {
   179  					t.Skipf("%q net not supported on Windows, skipping", tc.wantCfg.Network)
   180  				}
   181  			}
   182  
   183  			got, err := parseInstanceConfig(tc.dir, tc.instance, mockClient)
   184  			if tc.wantCfg == wantErr {
   185  				if err != nil {
   186  					return // pass. an error was expected and returned.
   187  				}
   188  				t.Fatalf("parseInstanceConfig(%s, %s) = %+v, wanted error", tc.dir, tc.instance, got)
   189  			}
   190  			if err != nil {
   191  				t.Fatalf("parseInstanceConfig(%s, %s) had unexpected error: %v", tc.dir, tc.instance, err)
   192  			}
   193  
   194  			if tc.wantCfg.Address == anyLoopbackAddress {
   195  				host, _, err := net.SplitHostPort(got.Address)
   196  				if err != nil {
   197  					t.Fatalf("net.SplitHostPort(%v): %v", got.Address, err)
   198  				}
   199  				ip := net.ParseIP(host)
   200  				if !ip.IsLoopback() {
   201  					t.Fatalf("want loopback, got addr: %v", got.Address)
   202  				}
   203  
   204  				// use a placeholder address, so the rest of the config can be compared
   205  				got.Address = "<loopback>"
   206  				tc.wantCfg.Address = got.Address
   207  			}
   208  
   209  			if got != tc.wantCfg {
   210  				t.Errorf("parseInstanceConfig(%s, %s) = %+v, want %+v", tc.dir, tc.instance, got, tc.wantCfg)
   211  			}
   212  		})
   213  	}
   214  }
   215  

View as plain text