github.com/vmware/govmomi@v0.51.0/vim25/soap/client_test.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package soap
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  	"net/http"
    11  	"net/url"
    12  	"os"
    13  	"reflect"
    14  	"testing"
    15  )
    16  
    17  type mockRT struct{}
    18  
    19  func (m mockRT) RoundTrip(req *http.Request) (*http.Response, error) {
    20  	var res http.Response
    21  	res.Header = req.Header.Clone()
    22  	return &res, nil
    23  }
    24  
    25  func TestUserAgent(t *testing.T) {
    26  	tests := []struct {
    27  		name  string
    28  		agent string
    29  	}{
    30  		{name: "default agent", agent: ""},
    31  		{name: "custom agent", agent: "govmomi-test/0.0.0"},
    32  	}
    33  
    34  	const rawURL = "https://vcenter.local"
    35  	u, err := url.Parse(rawURL)
    36  	if err != nil {
    37  		t.Fatalf("parse url: %v", err)
    38  	}
    39  
    40  	for _, test := range tests {
    41  		t.Run(test.name, func(t *testing.T) {
    42  			c := NewClient(u, false)
    43  			c.Transport = &mockRT{}
    44  
    45  			req, err := http.NewRequest(http.MethodPost, rawURL, nil)
    46  			if err != nil {
    47  				t.Fatalf("create request: %v", err)
    48  			}
    49  
    50  			if test.agent != "" {
    51  				c.UserAgent = test.agent
    52  			}
    53  
    54  			if err = c.Do(context.Background(), req, func(response *http.Response) error {
    55  				got := response.Header.Get("user-agent")
    56  				want := func() string {
    57  					if test.agent == "" {
    58  						return defaultUserAgent
    59  					}
    60  					return test.agent
    61  				}
    62  
    63  				if got != want() {
    64  					return fmt.Errorf("user-agent header mismatch: got=%s want=%s", got, want())
    65  				}
    66  				return nil
    67  			}); err != nil {
    68  				t.Errorf("user-agent header validation failed: %v", err)
    69  			}
    70  		})
    71  	}
    72  }
    73  
    74  func TestSplitHostPort(t *testing.T) {
    75  	tests := []struct {
    76  		url  string
    77  		host string
    78  		port string
    79  	}{
    80  		{"127.0.0.1", "127.0.0.1", ""},
    81  		{"*:1234", "*", "1234"},
    82  		{"127.0.0.1:80", "127.0.0.1", "80"},
    83  		{"[::1]:6767", "[::1]", "6767"},
    84  		{"[::1]", "[::1]", ""},
    85  	}
    86  
    87  	for _, test := range tests {
    88  		host, port := splitHostPort(test.url)
    89  		if host != test.host {
    90  			t.Errorf("(%s) %s != %s", test.url, host, test.host)
    91  		}
    92  		if port != test.port {
    93  			t.Errorf("(%s) %s != %s", test.url, port, test.port)
    94  		}
    95  	}
    96  }
    97  
    98  func TestMultipleCAPaths(t *testing.T) {
    99  	err := setCAsOnClient("fixtures/invalid-cert.pem:fixtures/valid-cert.pem")
   100  
   101  	certErr, ok := err.(errInvalidCACertificate)
   102  	if !ok {
   103  		t.Fatalf("Expected errInvalidCACertificate to occur")
   104  	}
   105  	if certErr.File != "fixtures/invalid-cert.pem" {
   106  		t.Fatalf("Expected Err to show invalid file")
   107  	}
   108  }
   109  
   110  func TestInvalidRootCAPath(t *testing.T) {
   111  	err := setCAsOnClient("fixtures/there-is-no-such-file")
   112  
   113  	if _, ok := err.(*os.PathError); !ok {
   114  		t.Fatalf("os.PathError should have occurred: %#v", err)
   115  	}
   116  }
   117  
   118  func TestValidRootCAs(t *testing.T) {
   119  	err := setCAsOnClient("fixtures/valid-cert.pem")
   120  	if err != nil {
   121  		t.Fatalf("Err should not have occurred: %#v", err)
   122  	}
   123  }
   124  
   125  func TestInvalidRootCAs(t *testing.T) {
   126  	err := setCAsOnClient("fixtures/invalid-cert.pem")
   127  
   128  	certErr, ok := err.(errInvalidCACertificate)
   129  	if !ok {
   130  		t.Fatalf("Expected errInvalidCACertificate to occur")
   131  	}
   132  	if certErr.File != "fixtures/invalid-cert.pem" {
   133  		t.Fatalf("Expected Err to show invalid file")
   134  	}
   135  }
   136  
   137  func setCAsOnClient(cas string) error {
   138  	url := &url.URL{
   139  		Scheme: "https",
   140  		Host:   "some.host.tld:8080",
   141  	}
   142  	insecure := false
   143  
   144  	client := NewClient(url, insecure)
   145  
   146  	return client.SetRootCAs(cas)
   147  }
   148  
   149  func TestParseURL(t *testing.T) {
   150  	tests := []struct {
   151  		name    string
   152  		s       string
   153  		want    *url.URL
   154  		wantErr bool
   155  	}{
   156  		{
   157  			name: "empty URL should return null",
   158  			want: nil,
   159  		},
   160  		{
   161  			name: "just endpoint should return full URL",
   162  			s:    "some.vcenter.tld",
   163  			want: &url.URL{
   164  				Scheme: "https",
   165  				Path:   "/sdk",
   166  				Host:   "some.vcenter.tld",
   167  				User:   url.UserPassword("", ""),
   168  			},
   169  		},
   170  		{
   171  			name: "URL with / on suffix should be trimmed",
   172  			s:    "https://some.vcenter.tld/",
   173  			want: &url.URL{
   174  				Scheme: "https",
   175  				Path:   "/sdk",
   176  				Host:   "some.vcenter.tld",
   177  				User:   url.UserPassword("", ""),
   178  			},
   179  		},
   180  		{
   181  			name: "URL with user and password should be used",
   182  			s:    "https://user:password@some.vcenter.tld",
   183  			want: &url.URL{
   184  				Scheme: "https",
   185  				Path:   "/sdk",
   186  				Host:   "some.vcenter.tld",
   187  				User:   url.UserPassword("user", "password"),
   188  			},
   189  		},
   190  		{
   191  			name: "existing path should be used",
   192  			s:    "https://some.vcenter.tld/othersdk",
   193  			want: &url.URL{
   194  				Scheme: "https",
   195  				Path:   "/othersdk",
   196  				Host:   "some.vcenter.tld",
   197  				User:   url.UserPassword("", ""),
   198  			},
   199  		},
   200  		{
   201  			name:    "Invalid URL should be rejected",
   202  			s:       "https://user:password@some.vcenter.tld:xpto1234",
   203  			want:    nil,
   204  			wantErr: true,
   205  		},
   206  	}
   207  	for _, tt := range tests {
   208  		t.Run(tt.name, func(t *testing.T) {
   209  			got, err := ParseURL(tt.s)
   210  			if (err != nil) != tt.wantErr {
   211  				t.Errorf("ParseURL() error = %v, wantErr %v", err, tt.wantErr)
   212  				return
   213  			}
   214  			if !reflect.DeepEqual(got, tt.want) {
   215  				t.Errorf("ParseURL() = %v, want %v", got, tt.want)
   216  			}
   217  		})
   218  	}
   219  }
   220  
   221  func TestSessionCookie(t *testing.T) {
   222  	u := &url.URL{
   223  		Scheme: "http",
   224  		Host:   "localhost:1080",
   225  		Path:   "sdk", // see comment in Client.SessionCookie
   226  	}
   227  
   228  	c := NewClient(u, true)
   229  
   230  	cookie := &http.Cookie{
   231  		Name:     SessionCookieName,
   232  		Value:    "ANY",
   233  		Path:     "/",
   234  		Domain:   "localhost",
   235  		HttpOnly: true,
   236  		Secure:   false,
   237  	}
   238  
   239  	c.Jar.SetCookies(u, []*http.Cookie{cookie})
   240  
   241  	val := c.SessionCookie()
   242  	if val == nil {
   243  		t.Fatal("no session cookie")
   244  	}
   245  }