storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/endpoint_test.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2017,2018,2019 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package cmd
    18  
    19  import (
    20  	"fmt"
    21  	"net"
    22  	"net/url"
    23  	"path/filepath"
    24  	"reflect"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/minio/minio-go/v7/pkg/set"
    29  )
    30  
    31  func TestNewEndpoint(t *testing.T) {
    32  	u2, _ := url.Parse("https://example.org/path")
    33  	u4, _ := url.Parse("http://192.168.253.200/path")
    34  	rootSlashFoo, _ := filepath.Abs("/foo")
    35  	testCases := []struct {
    36  		arg              string
    37  		expectedEndpoint Endpoint
    38  		expectedType     EndpointType
    39  		expectedErr      error
    40  	}{
    41  		{"/foo", Endpoint{URL: &url.URL{Path: rootSlashFoo}, IsLocal: true}, PathEndpointType, nil},
    42  		{"https://example.org/path", Endpoint{URL: u2, IsLocal: false}, URLEndpointType, nil},
    43  		{"http://192.168.253.200/path", Endpoint{URL: u4, IsLocal: false}, URLEndpointType, nil},
    44  		{"", Endpoint{}, -1, fmt.Errorf("empty or root endpoint is not supported")},
    45  		{SlashSeparator, Endpoint{}, -1, fmt.Errorf("empty or root endpoint is not supported")},
    46  		{`\`, Endpoint{}, -1, fmt.Errorf("empty or root endpoint is not supported")},
    47  		{"c://foo", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format")},
    48  		{"ftp://foo", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format")},
    49  		{"http://server/path?location", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format")},
    50  		{"http://:/path", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format: invalid port number")},
    51  		{"http://:8080/path", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format: empty host name")},
    52  		{"http://server:/path", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format: invalid port number")},
    53  		{"https://93.184.216.34:808080/path", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format: port number must be between 1 to 65535")},
    54  		{"http://server:8080//", Endpoint{}, -1, fmt.Errorf("empty or root path is not supported in URL endpoint")},
    55  		{"http://server:8080/", Endpoint{}, -1, fmt.Errorf("empty or root path is not supported in URL endpoint")},
    56  		{"192.168.1.210:9000", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format: missing scheme http or https")},
    57  	}
    58  
    59  	for i, test := range testCases {
    60  		t.Run(fmt.Sprint("case-", i), func(t *testing.T) {
    61  			endpoint, err := NewEndpoint(test.arg)
    62  			if err == nil {
    63  				err = endpoint.UpdateIsLocal()
    64  			}
    65  
    66  			if test.expectedErr == nil {
    67  				if err != nil {
    68  					t.Errorf("error: expected = <nil>, got = %v", err)
    69  				}
    70  			} else if err == nil {
    71  				t.Errorf("error: expected = %v, got = <nil>", test.expectedErr)
    72  			} else if test.expectedErr.Error() != err.Error() {
    73  				t.Errorf("error: expected = %v, got = %v", test.expectedErr, err)
    74  			}
    75  
    76  			if err == nil {
    77  				if (test.expectedEndpoint.URL == nil) != (endpoint.URL == nil) {
    78  					t.Errorf("endpoint url: expected = %#v, got = %#v", test.expectedEndpoint.URL, endpoint.URL)
    79  					return
    80  				} else if test.expectedEndpoint.URL.String() != endpoint.URL.String() {
    81  					t.Errorf("endpoint url: expected = %#v, got = %#v", test.expectedEndpoint.URL.String(), endpoint.URL.String())
    82  					return
    83  				}
    84  				if !reflect.DeepEqual(test.expectedEndpoint, endpoint) {
    85  					t.Errorf("endpoint: expected = %#v, got = %#v", test.expectedEndpoint, endpoint)
    86  				}
    87  			}
    88  
    89  			if err == nil && test.expectedType != endpoint.Type() {
    90  				t.Errorf("type: expected = %+v, got = %+v", test.expectedType, endpoint.Type())
    91  			}
    92  		})
    93  	}
    94  }
    95  
    96  func TestNewEndpoints(t *testing.T) {
    97  	testCases := []struct {
    98  		args        []string
    99  		expectedErr error
   100  	}{
   101  		{[]string{"/d1", "/d2", "/d3", "/d4"}, nil},
   102  		{[]string{"http://localhost/d1", "http://localhost/d2", "http://localhost/d3", "http://localhost/d4"}, nil},
   103  		{[]string{"http://example.org/d1", "http://example.com/d1", "http://example.net/d1", "http://example.edu/d1"}, nil},
   104  		{[]string{"http://localhost/d1", "http://localhost/d2", "http://example.org/d1", "http://example.org/d2"}, nil},
   105  		{[]string{"https://localhost:9000/d1", "https://localhost:9001/d2", "https://localhost:9002/d3", "https://localhost:9003/d4"}, nil},
   106  		// // It is valid WRT endpoint list that same path is expected with different port on same server.
   107  		{[]string{"https://127.0.0.1:9000/d1", "https://127.0.0.1:9001/d1", "https://127.0.0.1:9002/d1", "https://127.0.0.1:9003/d1"}, nil},
   108  		{[]string{"d1", "d2", "d3", "d1"}, fmt.Errorf("duplicate endpoints found")},
   109  		{[]string{"d1", "d2", "d3", "./d1"}, fmt.Errorf("duplicate endpoints found")},
   110  		{[]string{"http://localhost/d1", "http://localhost/d2", "http://localhost/d1", "http://localhost/d4"}, fmt.Errorf("duplicate endpoints found")},
   111  		{[]string{"ftp://server/d1", "http://server/d2", "http://server/d3", "http://server/d4"}, fmt.Errorf("'ftp://server/d1': invalid URL endpoint format")},
   112  		{[]string{"d1", "http://localhost/d2", "d3", "d4"}, fmt.Errorf("mixed style endpoints are not supported")},
   113  		{[]string{"http://example.org/d1", "https://example.com/d1", "http://example.net/d1", "https://example.edut/d1"}, fmt.Errorf("mixed scheme is not supported")},
   114  		{[]string{"192.168.1.210:9000/tmp/dir0", "192.168.1.210:9000/tmp/dir1", "192.168.1.210:9000/tmp/dir2", "192.168.110:9000/tmp/dir3"}, fmt.Errorf("'192.168.1.210:9000/tmp/dir0': invalid URL endpoint format: missing scheme http or https")},
   115  	}
   116  
   117  	for _, testCase := range testCases {
   118  		_, err := NewEndpoints(testCase.args...)
   119  		if testCase.expectedErr == nil {
   120  			if err != nil {
   121  				t.Fatalf("error: expected = <nil>, got = %v", err)
   122  			}
   123  		} else if err == nil {
   124  			t.Fatalf("error: expected = %v, got = <nil>", testCase.expectedErr)
   125  		} else if testCase.expectedErr.Error() != err.Error() {
   126  			t.Fatalf("error: expected = %v, got = %v", testCase.expectedErr, err)
   127  		}
   128  	}
   129  }
   130  
   131  func TestCreateEndpoints(t *testing.T) {
   132  	// Filter ipList by IPs those do not start with '127.'.
   133  	nonLoopBackIPs := localIP4.FuncMatch(func(ip string, matchString string) bool {
   134  		return !net.ParseIP(ip).IsLoopback()
   135  	}, "")
   136  	if len(nonLoopBackIPs) == 0 {
   137  		t.Fatalf("No non-loop back IP address found for this host")
   138  	}
   139  	nonLoopBackIP := nonLoopBackIPs.ToSlice()[0]
   140  
   141  	mustAbs := func(s string) string {
   142  		s, err := filepath.Abs(s)
   143  		if err != nil {
   144  			t.Fatal(err)
   145  		}
   146  		return s
   147  	}
   148  	getExpectedEndpoints := func(args []string, prefix string) ([]*url.URL, []bool) {
   149  		var URLs []*url.URL
   150  		var localFlags []bool
   151  		for _, arg := range args {
   152  			u, _ := url.Parse(arg)
   153  			URLs = append(URLs, u)
   154  			localFlags = append(localFlags, strings.HasPrefix(arg, prefix))
   155  		}
   156  
   157  		return URLs, localFlags
   158  	}
   159  
   160  	case1Endpoint1 := "http://" + nonLoopBackIP + "/d1"
   161  	case1Endpoint2 := "http://" + nonLoopBackIP + "/d2"
   162  	args := []string{
   163  		"http://" + nonLoopBackIP + ":10000/d1",
   164  		"http://" + nonLoopBackIP + ":10000/d2",
   165  		"http://example.org:10000/d3",
   166  		"http://example.com:10000/d4",
   167  	}
   168  	case1URLs, case1LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":10000/")
   169  
   170  	case2Endpoint1 := "http://" + nonLoopBackIP + "/d1"
   171  	case2Endpoint2 := "http://" + nonLoopBackIP + ":9000/d2"
   172  	args = []string{
   173  		"http://" + nonLoopBackIP + ":10000/d1",
   174  		"http://" + nonLoopBackIP + ":9000/d2",
   175  		"http://example.org:10000/d3",
   176  		"http://example.com:10000/d4",
   177  	}
   178  	case2URLs, case2LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":10000/")
   179  
   180  	case3Endpoint1 := "http://" + nonLoopBackIP + "/d1"
   181  	args = []string{
   182  		"http://" + nonLoopBackIP + ":80/d1",
   183  		"http://example.org:9000/d2",
   184  		"http://example.com:80/d3",
   185  		"http://example.net:80/d4",
   186  	}
   187  	case3URLs, case3LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":80/")
   188  
   189  	case4Endpoint1 := "http://" + nonLoopBackIP + "/d1"
   190  	args = []string{
   191  		"http://" + nonLoopBackIP + ":9000/d1",
   192  		"http://example.org:9000/d2",
   193  		"http://example.com:9000/d3",
   194  		"http://example.net:9000/d4",
   195  	}
   196  	case4URLs, case4LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":9000/")
   197  
   198  	case5Endpoint1 := "http://" + nonLoopBackIP + ":9000/d1"
   199  	case5Endpoint2 := "http://" + nonLoopBackIP + ":9001/d2"
   200  	case5Endpoint3 := "http://" + nonLoopBackIP + ":9002/d3"
   201  	case5Endpoint4 := "http://" + nonLoopBackIP + ":9003/d4"
   202  	args = []string{
   203  		case5Endpoint1,
   204  		case5Endpoint2,
   205  		case5Endpoint3,
   206  		case5Endpoint4,
   207  	}
   208  	case5URLs, case5LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":9000/")
   209  
   210  	case6Endpoint := "http://" + nonLoopBackIP + ":9003/d4"
   211  	args = []string{
   212  		"http://localhost:9000/d1",
   213  		"http://localhost:9001/d2",
   214  		"http://127.0.0.1:9002/d3",
   215  		case6Endpoint,
   216  	}
   217  	case6URLs, case6LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":9003/")
   218  
   219  	testCases := []struct {
   220  		serverAddr         string
   221  		args               [][]string
   222  		expectedServerAddr string
   223  		expectedEndpoints  Endpoints
   224  		expectedSetupType  SetupType
   225  		expectedErr        error
   226  	}{
   227  		{"localhost", [][]string{}, "", Endpoints{}, -1, fmt.Errorf("address localhost: missing port in address")},
   228  
   229  		// FS Setup
   230  		{"localhost:9000", [][]string{{"http://localhost/d1"}}, "", Endpoints{}, -1, fmt.Errorf("use path style endpoint for FS setup")},
   231  		{":443", [][]string{{"/d1"}}, ":443", Endpoints{Endpoint{URL: &url.URL{Path: mustAbs("/d1")}, IsLocal: true}}, FSSetupType, nil},
   232  		{"localhost:10000", [][]string{{"/d1"}}, "localhost:10000", Endpoints{Endpoint{URL: &url.URL{Path: mustAbs("/d1")}, IsLocal: true}}, FSSetupType, nil},
   233  		{"localhost:9000", [][]string{{"https://127.0.0.1:9000/d1", "https://localhost:9001/d1", "https://example.com/d1", "https://example.com/d2"}}, "", Endpoints{}, -1, fmt.Errorf("path '/d1' can not be served by different port on same address")},
   234  
   235  		// Erasure Setup with PathEndpointType
   236  		{":1234", [][]string{{"/d1", "/d2", "/d3", "/d4"}}, ":1234",
   237  			Endpoints{
   238  				Endpoint{URL: &url.URL{Path: mustAbs("/d1")}, IsLocal: true},
   239  				Endpoint{URL: &url.URL{Path: mustAbs("/d2")}, IsLocal: true},
   240  				Endpoint{URL: &url.URL{Path: mustAbs("/d3")}, IsLocal: true},
   241  				Endpoint{URL: &url.URL{Path: mustAbs("/d4")}, IsLocal: true},
   242  			}, ErasureSetupType, nil},
   243  		// DistErasure Setup with URLEndpointType
   244  		{":9000", [][]string{{"http://localhost/d1", "http://localhost/d2", "http://localhost/d3", "http://localhost/d4"}}, ":9000", Endpoints{
   245  			Endpoint{URL: &url.URL{Scheme: "http", Host: "localhost", Path: "/d1"}, IsLocal: true},
   246  			Endpoint{URL: &url.URL{Scheme: "http", Host: "localhost", Path: "/d2"}, IsLocal: true},
   247  			Endpoint{URL: &url.URL{Scheme: "http", Host: "localhost", Path: "/d3"}, IsLocal: true},
   248  			Endpoint{URL: &url.URL{Scheme: "http", Host: "localhost", Path: "/d4"}, IsLocal: true},
   249  		}, ErasureSetupType, nil},
   250  		// DistErasure Setup with URLEndpointType having mixed naming to local host.
   251  		{"127.0.0.1:10000", [][]string{{"http://localhost/d1", "http://localhost/d2", "http://127.0.0.1/d3", "http://127.0.0.1/d4"}}, "", Endpoints{}, -1, fmt.Errorf("all local endpoints should not have different hostnames/ips")},
   252  
   253  		{":9001", [][]string{{"http://10.0.0.1:9000/export", "http://10.0.0.2:9000/export", "http://" + nonLoopBackIP + ":9001/export", "http://10.0.0.2:9001/export"}}, "", Endpoints{}, -1, fmt.Errorf("path '/export' can not be served by different port on same address")},
   254  
   255  		{":9000", [][]string{{"http://127.0.0.1:9000/export", "http://" + nonLoopBackIP + ":9000/export", "http://10.0.0.1:9000/export", "http://10.0.0.2:9000/export"}}, "", Endpoints{}, -1, fmt.Errorf("path '/export' cannot be served by different address on same server")},
   256  
   257  		// DistErasure type
   258  		{"127.0.0.1:10000", [][]string{{case1Endpoint1, case1Endpoint2, "http://example.org/d3", "http://example.com/d4"}}, "127.0.0.1:10000", Endpoints{
   259  			Endpoint{URL: case1URLs[0], IsLocal: case1LocalFlags[0]},
   260  			Endpoint{URL: case1URLs[1], IsLocal: case1LocalFlags[1]},
   261  			Endpoint{URL: case1URLs[2], IsLocal: case1LocalFlags[2]},
   262  			Endpoint{URL: case1URLs[3], IsLocal: case1LocalFlags[3]},
   263  		}, DistErasureSetupType, nil},
   264  
   265  		{"127.0.0.1:10000", [][]string{{case2Endpoint1, case2Endpoint2, "http://example.org/d3", "http://example.com/d4"}}, "127.0.0.1:10000", Endpoints{
   266  			Endpoint{URL: case2URLs[0], IsLocal: case2LocalFlags[0]},
   267  			Endpoint{URL: case2URLs[1], IsLocal: case2LocalFlags[1]},
   268  			Endpoint{URL: case2URLs[2], IsLocal: case2LocalFlags[2]},
   269  			Endpoint{URL: case2URLs[3], IsLocal: case2LocalFlags[3]},
   270  		}, DistErasureSetupType, nil},
   271  
   272  		{":80", [][]string{{case3Endpoint1, "http://example.org:9000/d2", "http://example.com/d3", "http://example.net/d4"}}, ":80", Endpoints{
   273  			Endpoint{URL: case3URLs[0], IsLocal: case3LocalFlags[0]},
   274  			Endpoint{URL: case3URLs[1], IsLocal: case3LocalFlags[1]},
   275  			Endpoint{URL: case3URLs[2], IsLocal: case3LocalFlags[2]},
   276  			Endpoint{URL: case3URLs[3], IsLocal: case3LocalFlags[3]},
   277  		}, DistErasureSetupType, nil},
   278  
   279  		{":9000", [][]string{{case4Endpoint1, "http://example.org/d2", "http://example.com/d3", "http://example.net/d4"}}, ":9000", Endpoints{
   280  			Endpoint{URL: case4URLs[0], IsLocal: case4LocalFlags[0]},
   281  			Endpoint{URL: case4URLs[1], IsLocal: case4LocalFlags[1]},
   282  			Endpoint{URL: case4URLs[2], IsLocal: case4LocalFlags[2]},
   283  			Endpoint{URL: case4URLs[3], IsLocal: case4LocalFlags[3]},
   284  		}, DistErasureSetupType, nil},
   285  
   286  		{":9000", [][]string{{case5Endpoint1, case5Endpoint2, case5Endpoint3, case5Endpoint4}}, ":9000", Endpoints{
   287  			Endpoint{URL: case5URLs[0], IsLocal: case5LocalFlags[0]},
   288  			Endpoint{URL: case5URLs[1], IsLocal: case5LocalFlags[1]},
   289  			Endpoint{URL: case5URLs[2], IsLocal: case5LocalFlags[2]},
   290  			Endpoint{URL: case5URLs[3], IsLocal: case5LocalFlags[3]},
   291  		}, DistErasureSetupType, nil},
   292  
   293  		// DistErasure Setup using only local host.
   294  		{":9003", [][]string{{"http://localhost:9000/d1", "http://localhost:9001/d2", "http://127.0.0.1:9002/d3", case6Endpoint}}, ":9003", Endpoints{
   295  			Endpoint{URL: case6URLs[0], IsLocal: case6LocalFlags[0]},
   296  			Endpoint{URL: case6URLs[1], IsLocal: case6LocalFlags[1]},
   297  			Endpoint{URL: case6URLs[2], IsLocal: case6LocalFlags[2]},
   298  			Endpoint{URL: case6URLs[3], IsLocal: case6LocalFlags[3]},
   299  		}, DistErasureSetupType, nil},
   300  	}
   301  
   302  	for _, testCase := range testCases {
   303  		testCase := testCase
   304  		t.Run("", func(t *testing.T) {
   305  			endpoints, setupType, err := CreateEndpoints(testCase.serverAddr, false, testCase.args...)
   306  			if err == nil && testCase.expectedErr != nil {
   307  				t.Errorf("error: expected = %v, got = <nil>", testCase.expectedErr)
   308  			}
   309  			if err == nil {
   310  				if setupType != testCase.expectedSetupType {
   311  					t.Errorf("setupType: expected = %v, got = %v", testCase.expectedSetupType, setupType)
   312  				}
   313  				if len(endpoints) != len(testCase.expectedEndpoints) {
   314  					t.Errorf("endpoints: expected = %d, got = %d", len(testCase.expectedEndpoints),
   315  						len(endpoints))
   316  				} else {
   317  					for i, endpoint := range endpoints {
   318  						if testCase.expectedEndpoints[i].String() != endpoint.String() {
   319  							t.Errorf("endpoints: expected = %s, got = %s",
   320  								testCase.expectedEndpoints[i],
   321  								endpoint)
   322  						}
   323  					}
   324  				}
   325  			}
   326  			if err != nil && testCase.expectedErr == nil {
   327  				t.Errorf("error: expected = <nil>, got = %v, testCase: %v", err, testCase)
   328  			}
   329  		})
   330  	}
   331  }
   332  
   333  // Tests get local peer functionality, local peer is supposed to only return one entry per minio service.
   334  // So it means that if you have say localhost:9000 and localhost:9001 as endpointArgs then localhost:9001
   335  // is considered a remote service from localhost:9000 perspective.
   336  func TestGetLocalPeer(t *testing.T) {
   337  	testCases := []struct {
   338  		endpointArgs   []string
   339  		expectedResult string
   340  	}{
   341  		{[]string{"/d1", "/d2", "d3", "d4"}, "127.0.0.1:9000"},
   342  		{[]string{"http://localhost:9000/d1", "http://localhost:9000/d2", "http://example.org:9000/d3", "http://example.com:9000/d4"},
   343  			"localhost:9000"},
   344  		{[]string{"http://localhost:9000/d1", "http://example.org:9000/d2", "http://example.com:9000/d3", "http://example.net:9000/d4"},
   345  			"localhost:9000"},
   346  		{[]string{"http://localhost:9000/d1", "http://localhost:9001/d2", "http://localhost:9002/d3", "http://localhost:9003/d4"},
   347  			"localhost:9000"},
   348  	}
   349  
   350  	for i, testCase := range testCases {
   351  		zendpoints := mustGetPoolEndpoints(testCase.endpointArgs...)
   352  		if !zendpoints[0].Endpoints[0].IsLocal {
   353  			if err := zendpoints[0].Endpoints.UpdateIsLocal(false); err != nil {
   354  				t.Fatalf("error: expected = <nil>, got = %v", err)
   355  			}
   356  		}
   357  		localPeer := GetLocalPeer(zendpoints, "", "9000")
   358  		if localPeer != testCase.expectedResult {
   359  			t.Fatalf("Test %d: expected: %v, got: %v", i+1, testCase.expectedResult, localPeer)
   360  		}
   361  	}
   362  }
   363  
   364  func TestGetRemotePeers(t *testing.T) {
   365  	tempGlobalMinioPort := globalMinioPort
   366  	defer func() {
   367  		globalMinioPort = tempGlobalMinioPort
   368  	}()
   369  	globalMinioPort = "9000"
   370  
   371  	testCases := []struct {
   372  		endpointArgs   []string
   373  		expectedResult []string
   374  		expectedLocal  string
   375  	}{
   376  		{[]string{"/d1", "/d2", "d3", "d4"}, []string{}, ""},
   377  		{[]string{"http://localhost:9000/d1", "http://localhost:9000/d2", "http://example.org:9000/d3", "http://example.com:9000/d4"}, []string{"example.com:9000", "example.org:9000", "localhost:9000"}, "localhost:9000"},
   378  		{[]string{"http://localhost:9000/d1", "http://localhost:10000/d2", "http://example.org:9000/d3", "http://example.com:9000/d4"}, []string{"example.com:9000", "example.org:9000", "localhost:10000", "localhost:9000"}, "localhost:9000"},
   379  		{[]string{"http://localhost:9000/d1", "http://example.org:9000/d2", "http://example.com:9000/d3", "http://example.net:9000/d4"}, []string{"example.com:9000", "example.net:9000", "example.org:9000", "localhost:9000"}, "localhost:9000"},
   380  		{[]string{"http://localhost:9000/d1", "http://localhost:9001/d2", "http://localhost:9002/d3", "http://localhost:9003/d4"}, []string{"localhost:9000", "localhost:9001", "localhost:9002", "localhost:9003"}, "localhost:9000"},
   381  	}
   382  
   383  	for _, testCase := range testCases {
   384  		zendpoints := mustGetPoolEndpoints(testCase.endpointArgs...)
   385  		if !zendpoints[0].Endpoints[0].IsLocal {
   386  			if err := zendpoints[0].Endpoints.UpdateIsLocal(false); err != nil {
   387  				t.Errorf("error: expected = <nil>, got = %v", err)
   388  			}
   389  		}
   390  		remotePeers, local := zendpoints.peers()
   391  		if !reflect.DeepEqual(remotePeers, testCase.expectedResult) {
   392  			t.Errorf("expected: %v, got: %v", testCase.expectedResult, remotePeers)
   393  		}
   394  		if local != testCase.expectedLocal {
   395  			t.Errorf("expected: %v, got: %v", testCase.expectedLocal, local)
   396  		}
   397  	}
   398  }
   399  
   400  func TestUpdateDomainIPs(t *testing.T) {
   401  	tempGlobalMinioPort := globalMinioPort
   402  	defer func() {
   403  		globalMinioPort = tempGlobalMinioPort
   404  	}()
   405  	globalMinioPort = "9000"
   406  
   407  	tempGlobalDomainIPs := globalDomainIPs
   408  	defer func() {
   409  		globalDomainIPs = tempGlobalDomainIPs
   410  	}()
   411  
   412  	ipv4TestCases := []struct {
   413  		endPoints      set.StringSet
   414  		expectedResult set.StringSet
   415  	}{
   416  		{set.NewStringSet(), set.NewStringSet()},
   417  		{set.CreateStringSet("localhost"), set.NewStringSet()},
   418  		{set.CreateStringSet("localhost", "10.0.0.1"), set.CreateStringSet("10.0.0.1:9000")},
   419  		{set.CreateStringSet("localhost:9001", "10.0.0.1"), set.CreateStringSet("10.0.0.1:9000")},
   420  		{set.CreateStringSet("localhost", "10.0.0.1:9001"), set.CreateStringSet("10.0.0.1:9001")},
   421  		{set.CreateStringSet("localhost:9000", "10.0.0.1:9001"), set.CreateStringSet("10.0.0.1:9001")},
   422  
   423  		{set.CreateStringSet("10.0.0.1", "10.0.0.2"), set.CreateStringSet("10.0.0.1:9000", "10.0.0.2:9000")},
   424  		{set.CreateStringSet("10.0.0.1:9001", "10.0.0.2"), set.CreateStringSet("10.0.0.1:9001", "10.0.0.2:9000")},
   425  		{set.CreateStringSet("10.0.0.1", "10.0.0.2:9002"), set.CreateStringSet("10.0.0.1:9000", "10.0.0.2:9002")},
   426  		{set.CreateStringSet("10.0.0.1:9001", "10.0.0.2:9002"), set.CreateStringSet("10.0.0.1:9001", "10.0.0.2:9002")},
   427  	}
   428  
   429  	for _, testCase := range ipv4TestCases {
   430  		globalDomainIPs = nil
   431  
   432  		updateDomainIPs(testCase.endPoints)
   433  
   434  		if !testCase.expectedResult.Equals(globalDomainIPs) {
   435  			t.Fatalf("error: expected = %s, got = %s", testCase.expectedResult, globalDomainIPs)
   436  		}
   437  	}
   438  }