mirror of https://github.com/minio/minio.git
				
				
				
			
		
			
				
	
	
		
			490 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			490 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Go
		
	
	
	
| /*
 | |
|  * MinIO Cloud Storage, (C) 2017 MinIO, Inc.
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  */
 | |
| 
 | |
| package cmd
 | |
| 
 | |
| import (
 | |
| 	"flag"
 | |
| 	"fmt"
 | |
| 	"net/url"
 | |
| 	"reflect"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/minio/cli"
 | |
| 	"github.com/minio/minio-go/v6/pkg/set"
 | |
| )
 | |
| 
 | |
| func TestSubOptimalEndpointInput(t *testing.T) {
 | |
| 	args1 := []string{"http://localhost/d1", "http://localhost/d2", "http://localhost/d3", "http://localhost/d4"}
 | |
| 	args2 := []string{"http://example.org/d1", "http://example.com/d1", "http://example.net/d1", "http://example.edu/d1"}
 | |
| 
 | |
| 	tests := []struct {
 | |
| 		setupType SetupType
 | |
| 		ctx       *cli.Context
 | |
| 		endpoints EndpointList
 | |
| 		isErr     bool
 | |
| 	}{
 | |
| 		{
 | |
| 			setupType: DistXLSetupType,
 | |
| 			ctx:       cli.NewContext(cli.NewApp(), flag.NewFlagSet("", flag.ContinueOnError), nil),
 | |
| 			endpoints: mustGetNewEndpointList(args1...),
 | |
| 			isErr:     false,
 | |
| 		},
 | |
| 		{
 | |
| 			setupType: DistXLSetupType,
 | |
| 			ctx:       cli.NewContext(cli.NewApp(), flag.NewFlagSet("", flag.ContinueOnError), nil),
 | |
| 			endpoints: mustGetNewEndpointList(args2...),
 | |
| 			isErr:     false,
 | |
| 		},
 | |
| 	}
 | |
| 	for i, test := range tests {
 | |
| 		test := test
 | |
| 		t.Run(fmt.Sprintf("Test%d", i+1), func(t *testing.T) {
 | |
| 			err := checkEndpointsSubOptimal(test.ctx, test.setupType, test.endpoints)
 | |
| 			if test.isErr && err == nil {
 | |
| 				t.Error("expected err but found nil")
 | |
| 			}
 | |
| 			if !test.isErr && err != nil {
 | |
| 				t.Errorf("expected err nil but found an err %s", err)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestNewEndpoint(t *testing.T) {
 | |
| 	u1, _ := url.Parse("http://localhost/path")
 | |
| 	u2, _ := url.Parse("https://example.org/path")
 | |
| 	u3, _ := url.Parse("http://127.0.0.1:8080/path")
 | |
| 	u4, _ := url.Parse("http://192.168.253.200/path")
 | |
| 
 | |
| 	testCases := []struct {
 | |
| 		arg              string
 | |
| 		expectedEndpoint Endpoint
 | |
| 		expectedType     EndpointType
 | |
| 		expectedErr      error
 | |
| 	}{
 | |
| 		{"foo", Endpoint{URL: &url.URL{Path: "foo"}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{"/foo", Endpoint{URL: &url.URL{Path: "/foo"}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{`\foo`, Endpoint{URL: &url.URL{Path: `\foo`}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{"C", Endpoint{URL: &url.URL{Path: `C`}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{"C:", Endpoint{URL: &url.URL{Path: `C:`}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{"C:/", Endpoint{URL: &url.URL{Path: "C:"}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{`C:\`, Endpoint{URL: &url.URL{Path: `C:\`}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{`C:\foo`, Endpoint{URL: &url.URL{Path: `C:\foo`}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{"C:/foo", Endpoint{URL: &url.URL{Path: "C:/foo"}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{`C:\\foo`, Endpoint{URL: &url.URL{Path: `C:\\foo`}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{"http:path", Endpoint{URL: &url.URL{Path: "http:path"}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{"http:/path", Endpoint{URL: &url.URL{Path: "http:/path"}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{"http:///path", Endpoint{URL: &url.URL{Path: "http:/path"}, IsLocal: true}, PathEndpointType, nil},
 | |
| 		{"http://localhost/path", Endpoint{URL: u1, IsLocal: true, HostName: "localhost"}, URLEndpointType, nil},
 | |
| 		{"http://localhost/path//", Endpoint{URL: u1, IsLocal: true, HostName: "localhost"}, URLEndpointType, nil},
 | |
| 		{"https://example.org/path", Endpoint{URL: u2, IsLocal: false, HostName: "example.org"}, URLEndpointType, nil},
 | |
| 		{"http://127.0.0.1:8080/path", Endpoint{URL: u3, IsLocal: true, HostName: "127.0.0.1"}, URLEndpointType, nil},
 | |
| 		{"http://192.168.253.200/path", Endpoint{URL: u4, IsLocal: false, HostName: "192.168.253.200"}, URLEndpointType, nil},
 | |
| 		{"", Endpoint{}, -1, fmt.Errorf("empty or root endpoint is not supported")},
 | |
| 		{SlashSeparator, Endpoint{}, -1, fmt.Errorf("empty or root endpoint is not supported")},
 | |
| 		{`\`, Endpoint{}, -1, fmt.Errorf("empty or root endpoint is not supported")},
 | |
| 		{"c://foo", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format")},
 | |
| 		{"ftp://foo", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format")},
 | |
| 		{"http://server/path?location", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format")},
 | |
| 		{"http://:/path", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format: invalid port number")},
 | |
| 		{"http://:8080/path", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format: empty host name")},
 | |
| 		{"http://server:/path", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format: invalid port number")},
 | |
| 		{"https://93.184.216.34:808080/path", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format: port number must be between 1 to 65535")},
 | |
| 		{"http://server:8080//", Endpoint{}, -1, fmt.Errorf("empty or root path is not supported in URL endpoint")},
 | |
| 		{"http://server:8080/", Endpoint{}, -1, fmt.Errorf("empty or root path is not supported in URL endpoint")},
 | |
| 		{"192.168.1.210:9000", Endpoint{}, -1, fmt.Errorf("invalid URL endpoint format: missing scheme http or https")},
 | |
| 	}
 | |
| 
 | |
| 	for _, testCase := range testCases {
 | |
| 		endpoint, err := NewEndpoint(testCase.arg)
 | |
| 		if err == nil {
 | |
| 			err = endpoint.UpdateIsLocal()
 | |
| 		}
 | |
| 
 | |
| 		if testCase.expectedErr == nil {
 | |
| 			if err != nil {
 | |
| 				t.Fatalf("error: expected = <nil>, got = %v", err)
 | |
| 			}
 | |
| 		} else if err == nil {
 | |
| 			t.Fatalf("error: expected = %v, got = <nil>", testCase.expectedErr)
 | |
| 		} else if testCase.expectedErr.Error() != err.Error() {
 | |
| 			t.Fatalf("error: expected = %v, got = %v", testCase.expectedErr, err)
 | |
| 		}
 | |
| 
 | |
| 		if err == nil && !reflect.DeepEqual(testCase.expectedEndpoint, endpoint) {
 | |
| 			t.Fatalf("endpoint: expected = %+v, got = %+v", testCase.expectedEndpoint, endpoint)
 | |
| 		}
 | |
| 
 | |
| 		if err == nil && testCase.expectedType != endpoint.Type() {
 | |
| 			t.Fatalf("type: expected = %+v, got = %+v", testCase.expectedType, endpoint.Type())
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestNewEndpointList(t *testing.T) {
 | |
| 	testCases := []struct {
 | |
| 		args        []string
 | |
| 		expectedErr error
 | |
| 	}{
 | |
| 		{[]string{"d1", "d2", "d3", "d4"}, nil},
 | |
| 		{[]string{"/d1", "/d2", "/d3", "/d4"}, nil},
 | |
| 		{[]string{"http://localhost/d1", "http://localhost/d2", "http://localhost/d3", "http://localhost/d4"}, nil},
 | |
| 		{[]string{"http://example.org/d1", "http://example.com/d1", "http://example.net/d1", "http://example.edu/d1"}, nil},
 | |
| 		{[]string{"http://localhost/d1", "http://localhost/d2", "http://example.org/d1", "http://example.org/d2"}, nil},
 | |
| 		{[]string{"https://localhost:9000/d1", "https://localhost:9001/d2", "https://localhost:9002/d3", "https://localhost:9003/d4"}, nil},
 | |
| 		// // It is valid WRT endpoint list that same path is expected with different port on same server.
 | |
| 		{[]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},
 | |
| 		{[]string{"d1", "d2", "d3", "d1"}, fmt.Errorf("duplicate endpoints found")},
 | |
| 		{[]string{"d1", "d2", "d3", "./d1"}, fmt.Errorf("duplicate endpoints found")},
 | |
| 		{[]string{"http://localhost/d1", "http://localhost/d2", "http://localhost/d1", "http://localhost/d4"}, fmt.Errorf("duplicate endpoints found")},
 | |
| 		{[]string{"ftp://server/d1", "http://server/d2", "http://server/d3", "http://server/d4"}, fmt.Errorf("'ftp://server/d1': invalid URL endpoint format")},
 | |
| 		{[]string{"d1", "http://localhost/d2", "d3", "d4"}, fmt.Errorf("mixed style endpoints are not supported")},
 | |
| 		{[]string{"http://example.org/d1", "https://example.com/d1", "http://example.net/d1", "https://example.edut/d1"}, fmt.Errorf("mixed scheme is not supported")},
 | |
| 		{[]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")},
 | |
| 	}
 | |
| 
 | |
| 	for _, testCase := range testCases {
 | |
| 		_, err := NewEndpointList(testCase.args...)
 | |
| 		if testCase.expectedErr == nil {
 | |
| 			if err != nil {
 | |
| 				t.Fatalf("error: expected = <nil>, got = %v", err)
 | |
| 			}
 | |
| 		} else if err == nil {
 | |
| 			t.Fatalf("error: expected = %v, got = <nil>", testCase.expectedErr)
 | |
| 		} else if testCase.expectedErr.Error() != err.Error() {
 | |
| 			t.Fatalf("error: expected = %v, got = %v", testCase.expectedErr, err)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestCreateEndpoints(t *testing.T) {
 | |
| 	// Filter ipList by IPs those do not start with '127.'.
 | |
| 	nonLoopBackIPs := localIP4.FuncMatch(func(ip string, matchString string) bool {
 | |
| 		return !strings.HasPrefix(ip, "127.")
 | |
| 	}, "")
 | |
| 	if len(nonLoopBackIPs) == 0 {
 | |
| 		t.Fatalf("No non-loop back IP address found for this host")
 | |
| 	}
 | |
| 	nonLoopBackIP := nonLoopBackIPs.ToSlice()[0]
 | |
| 
 | |
| 	getExpectedEndpoints := func(args []string, prefix string) ([]*url.URL, []bool) {
 | |
| 		var URLs []*url.URL
 | |
| 		var localFlags []bool
 | |
| 		for _, arg := range args {
 | |
| 			u, _ := url.Parse(arg)
 | |
| 			URLs = append(URLs, u)
 | |
| 			localFlags = append(localFlags, strings.HasPrefix(arg, prefix))
 | |
| 		}
 | |
| 
 | |
| 		return URLs, localFlags
 | |
| 	}
 | |
| 
 | |
| 	case1Endpoint1 := "http://" + nonLoopBackIP + "/d1"
 | |
| 	case1Endpoint2 := "http://" + nonLoopBackIP + "/d2"
 | |
| 	args := []string{
 | |
| 		"http://" + nonLoopBackIP + ":10000/d1",
 | |
| 		"http://" + nonLoopBackIP + ":10000/d2",
 | |
| 		"http://example.org:10000/d3",
 | |
| 		"http://example.com:10000/d4",
 | |
| 	}
 | |
| 	case1URLs, case1LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":10000/")
 | |
| 
 | |
| 	case2Endpoint1 := "http://" + nonLoopBackIP + "/d1"
 | |
| 	case2Endpoint2 := "http://" + nonLoopBackIP + ":9000/d2"
 | |
| 	args = []string{
 | |
| 		"http://" + nonLoopBackIP + ":10000/d1",
 | |
| 		"http://" + nonLoopBackIP + ":9000/d2",
 | |
| 		"http://example.org:10000/d3",
 | |
| 		"http://example.com:10000/d4",
 | |
| 	}
 | |
| 	case2URLs, case2LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":10000/")
 | |
| 
 | |
| 	case3Endpoint1 := "http://" + nonLoopBackIP + "/d1"
 | |
| 	args = []string{
 | |
| 		"http://" + nonLoopBackIP + ":80/d1",
 | |
| 		"http://example.org:9000/d2",
 | |
| 		"http://example.com:80/d3",
 | |
| 		"http://example.net:80/d4",
 | |
| 	}
 | |
| 	case3URLs, case3LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":80/")
 | |
| 
 | |
| 	case4Endpoint1 := "http://" + nonLoopBackIP + "/d1"
 | |
| 	args = []string{
 | |
| 		"http://" + nonLoopBackIP + ":9000/d1",
 | |
| 		"http://example.org:9000/d2",
 | |
| 		"http://example.com:9000/d3",
 | |
| 		"http://example.net:9000/d4",
 | |
| 	}
 | |
| 	case4URLs, case4LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":9000/")
 | |
| 
 | |
| 	case5Endpoint1 := "http://" + nonLoopBackIP + ":9000/d1"
 | |
| 	case5Endpoint2 := "http://" + nonLoopBackIP + ":9001/d2"
 | |
| 	case5Endpoint3 := "http://" + nonLoopBackIP + ":9002/d3"
 | |
| 	case5Endpoint4 := "http://" + nonLoopBackIP + ":9003/d4"
 | |
| 	args = []string{
 | |
| 		case5Endpoint1,
 | |
| 		case5Endpoint2,
 | |
| 		case5Endpoint3,
 | |
| 		case5Endpoint4,
 | |
| 	}
 | |
| 	case5URLs, case5LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":9000/")
 | |
| 
 | |
| 	case6Endpoint := "http://" + nonLoopBackIP + ":9003/d4"
 | |
| 	args = []string{
 | |
| 		"http://localhost:9000/d1",
 | |
| 		"http://localhost:9001/d2",
 | |
| 		"http://127.0.0.1:9002/d3",
 | |
| 		case6Endpoint,
 | |
| 	}
 | |
| 	case6URLs, case6LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":9003/")
 | |
| 
 | |
| 	testCases := []struct {
 | |
| 		serverAddr         string
 | |
| 		args               [][]string
 | |
| 		expectedServerAddr string
 | |
| 		expectedEndpoints  EndpointList
 | |
| 		expectedSetupType  SetupType
 | |
| 		expectedErr        error
 | |
| 	}{
 | |
| 		{"localhost", [][]string{}, "", EndpointList{}, -1, fmt.Errorf("address localhost: missing port in address")},
 | |
| 
 | |
| 		// FS Setup
 | |
| 		{"localhost:9000", [][]string{{"http://localhost/d1"}}, "", EndpointList{}, -1, fmt.Errorf("use path style endpoint for FS setup")},
 | |
| 		{":443", [][]string{{"d1"}}, ":443", EndpointList{Endpoint{URL: &url.URL{Path: "d1"}, IsLocal: true}}, FSSetupType, nil},
 | |
| 		{"localhost:10000", [][]string{{"/d1"}}, "localhost:10000", EndpointList{Endpoint{URL: &url.URL{Path: "/d1"}, IsLocal: true}}, FSSetupType, nil},
 | |
| 		{"localhost:10000", [][]string{{"./d1"}}, "localhost:10000", EndpointList{Endpoint{URL: &url.URL{Path: "d1"}, IsLocal: true}}, FSSetupType, nil},
 | |
| 		{"localhost:10000", [][]string{{`\d1`}}, "localhost:10000", EndpointList{Endpoint{URL: &url.URL{Path: `\d1`}, IsLocal: true}}, FSSetupType, nil},
 | |
| 		{"localhost:10000", [][]string{{`.\d1`}}, "localhost:10000", EndpointList{Endpoint{URL: &url.URL{Path: `.\d1`}, IsLocal: true}}, FSSetupType, nil},
 | |
| 		{":8080", [][]string{{"https://example.org/d1", "https://example.org/d2", "https://example.org/d3", "https://example.org/d4"}}, "", EndpointList{}, -1, fmt.Errorf("no endpoint pointing to the local machine is found")},
 | |
| 		{":8080", [][]string{{"https://example.org/d1", "https://example.com/d2", "https://example.net:8000/d3", "https://example.edu/d1"}}, "", EndpointList{}, -1, fmt.Errorf("no endpoint pointing to the local machine is found")},
 | |
| 		{"localhost:9000", [][]string{{"https://127.0.0.1:9000/d1", "https://localhost:9001/d1", "https://example.com/d1", "https://example.com/d2"}}, "", EndpointList{}, -1, fmt.Errorf("path '/d1' can not be served by different port on same address")},
 | |
| 		{"localhost:9000", [][]string{{"https://127.0.0.1:8000/d1", "https://localhost:9001/d2", "https://example.com/d1", "https://example.com/d2"}}, "", EndpointList{}, -1, fmt.Errorf("port number in server address must match with one of the port in local endpoints")},
 | |
| 		{"localhost:10000", [][]string{{"https://127.0.0.1:8000/d1", "https://localhost:8000/d2", "https://example.com/d1", "https://example.com/d2"}}, "", EndpointList{}, -1, fmt.Errorf("server address and local endpoint have different ports")},
 | |
| 
 | |
| 		// XL Setup with PathEndpointType
 | |
| 		{":1234", [][]string{{"/d1", "/d2", "d3", "d4"}}, ":1234",
 | |
| 			EndpointList{
 | |
| 				Endpoint{URL: &url.URL{Path: "/d1"}, IsLocal: true},
 | |
| 				Endpoint{URL: &url.URL{Path: "/d2"}, IsLocal: true},
 | |
| 				Endpoint{URL: &url.URL{Path: "d3"}, IsLocal: true},
 | |
| 				Endpoint{URL: &url.URL{Path: "d4"}, IsLocal: true},
 | |
| 			}, XLSetupType, nil},
 | |
| 		// XL Setup with URLEndpointType
 | |
| 		{":9000", [][]string{{"http://localhost/d1", "http://localhost/d2", "http://localhost/d3", "http://localhost/d4"}}, ":9000", EndpointList{
 | |
| 			Endpoint{URL: &url.URL{Path: "/d1"}, IsLocal: true},
 | |
| 			Endpoint{URL: &url.URL{Path: "/d2"}, IsLocal: true},
 | |
| 			Endpoint{URL: &url.URL{Path: "/d3"}, IsLocal: true},
 | |
| 			Endpoint{URL: &url.URL{Path: "/d4"}, IsLocal: true},
 | |
| 		}, XLSetupType, nil},
 | |
| 		// XL Setup with URLEndpointType having mixed naming to local host.
 | |
| 		{"127.0.0.1:10000", [][]string{{"http://localhost/d1", "http://localhost/d2", "http://127.0.0.1/d3", "http://127.0.0.1/d4"}}, ":10000", EndpointList{
 | |
| 			Endpoint{URL: &url.URL{Path: "/d1"}, IsLocal: true},
 | |
| 			Endpoint{URL: &url.URL{Path: "/d2"}, IsLocal: true},
 | |
| 			Endpoint{URL: &url.URL{Path: "/d3"}, IsLocal: true},
 | |
| 			Endpoint{URL: &url.URL{Path: "/d4"}, IsLocal: true},
 | |
| 		}, XLSetupType, nil},
 | |
| 		{":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"}}, "", EndpointList{}, -1, fmt.Errorf("path '/export' can not be served by different port on same address")},
 | |
| 
 | |
| 		{":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"}}, "", EndpointList{}, -1, fmt.Errorf("path '/export' cannot be served by different address on same server")},
 | |
| 
 | |
| 		{":9000", [][]string{{"http://localhost/d1", "http://localhost/d2", "http://example.org/d3", "http://example.com/d4"}}, "", EndpointList{}, -1, fmt.Errorf("'localhost' resolves to loopback address is not allowed for distributed XL")},
 | |
| 
 | |
| 		// DistXL type
 | |
| 		{"127.0.0.1:10000", [][]string{{case1Endpoint1, case1Endpoint2, "http://example.org/d3", "http://example.com/d4"}}, "127.0.0.1:10000", EndpointList{
 | |
| 			Endpoint{URL: case1URLs[0], IsLocal: case1LocalFlags[0], HostName: nonLoopBackIP},
 | |
| 			Endpoint{URL: case1URLs[1], IsLocal: case1LocalFlags[1], HostName: nonLoopBackIP},
 | |
| 			Endpoint{URL: case1URLs[2], IsLocal: case1LocalFlags[2], HostName: "example.org"},
 | |
| 			Endpoint{URL: case1URLs[3], IsLocal: case1LocalFlags[3], HostName: "example.com"},
 | |
| 		}, DistXLSetupType, nil},
 | |
| 
 | |
| 		{"127.0.0.1:10000", [][]string{{case2Endpoint1, case2Endpoint2, "http://example.org/d3", "http://example.com/d4"}}, "127.0.0.1:10000", EndpointList{
 | |
| 			Endpoint{URL: case2URLs[0], IsLocal: case2LocalFlags[0], HostName: nonLoopBackIP},
 | |
| 			Endpoint{URL: case2URLs[1], IsLocal: case2LocalFlags[1], HostName: nonLoopBackIP},
 | |
| 			Endpoint{URL: case2URLs[2], IsLocal: case2LocalFlags[2], HostName: "example.org"},
 | |
| 			Endpoint{URL: case2URLs[3], IsLocal: case2LocalFlags[3], HostName: "example.com"},
 | |
| 		}, DistXLSetupType, nil},
 | |
| 
 | |
| 		{":80", [][]string{{case3Endpoint1, "http://example.org:9000/d2", "http://example.com/d3", "http://example.net/d4"}}, ":80", EndpointList{
 | |
| 			Endpoint{URL: case3URLs[0], IsLocal: case3LocalFlags[0], HostName: nonLoopBackIP},
 | |
| 			Endpoint{URL: case3URLs[1], IsLocal: case3LocalFlags[1], HostName: "example.org"},
 | |
| 			Endpoint{URL: case3URLs[2], IsLocal: case3LocalFlags[2], HostName: "example.com"},
 | |
| 			Endpoint{URL: case3URLs[3], IsLocal: case3LocalFlags[3], HostName: "example.net"},
 | |
| 		}, DistXLSetupType, nil},
 | |
| 
 | |
| 		{":9000", [][]string{{case4Endpoint1, "http://example.org/d2", "http://example.com/d3", "http://example.net/d4"}}, ":9000", EndpointList{
 | |
| 			Endpoint{URL: case4URLs[0], IsLocal: case4LocalFlags[0], HostName: nonLoopBackIP},
 | |
| 			Endpoint{URL: case4URLs[1], IsLocal: case4LocalFlags[1], HostName: "example.org"},
 | |
| 			Endpoint{URL: case4URLs[2], IsLocal: case4LocalFlags[2], HostName: "example.com"},
 | |
| 			Endpoint{URL: case4URLs[3], IsLocal: case4LocalFlags[3], HostName: "example.net"},
 | |
| 		}, DistXLSetupType, nil},
 | |
| 
 | |
| 		{":9000", [][]string{{case5Endpoint1, case5Endpoint2, case5Endpoint3, case5Endpoint4}}, ":9000", EndpointList{
 | |
| 			Endpoint{URL: case5URLs[0], IsLocal: case5LocalFlags[0], HostName: nonLoopBackIP},
 | |
| 			Endpoint{URL: case5URLs[1], IsLocal: case5LocalFlags[1], HostName: nonLoopBackIP},
 | |
| 			Endpoint{URL: case5URLs[2], IsLocal: case5LocalFlags[2], HostName: nonLoopBackIP},
 | |
| 			Endpoint{URL: case5URLs[3], IsLocal: case5LocalFlags[3], HostName: nonLoopBackIP},
 | |
| 		}, DistXLSetupType, nil},
 | |
| 
 | |
| 		// DistXL Setup using only local host.
 | |
| 		{":9003", [][]string{{"http://localhost:9000/d1", "http://localhost:9001/d2", "http://127.0.0.1:9002/d3", case6Endpoint}}, ":9003", EndpointList{
 | |
| 			Endpoint{URL: case6URLs[0], IsLocal: case6LocalFlags[0], HostName: "localhost"},
 | |
| 			Endpoint{URL: case6URLs[1], IsLocal: case6LocalFlags[1], HostName: "localhost"},
 | |
| 			Endpoint{URL: case6URLs[2], IsLocal: case6LocalFlags[2], HostName: "127.0.0.1"},
 | |
| 			Endpoint{URL: case6URLs[3], IsLocal: case6LocalFlags[3], HostName: nonLoopBackIP},
 | |
| 		}, DistXLSetupType, nil},
 | |
| 	}
 | |
| 
 | |
| 	for i, testCase := range testCases {
 | |
| 		testCase := testCase
 | |
| 		t.Run(fmt.Sprintf("Test%d", i+1), func(t *testing.T) {
 | |
| 			serverAddr, endpoints, setupType, err := CreateEndpoints(testCase.serverAddr, testCase.args...)
 | |
| 			if err == nil {
 | |
| 				if testCase.expectedErr != nil {
 | |
| 					t.Fatalf("error: expected = %v, got = <nil>", testCase.expectedErr)
 | |
| 				} else {
 | |
| 					if serverAddr != testCase.expectedServerAddr {
 | |
| 						t.Fatalf("serverAddr: expected = %v, got = %v", testCase.expectedServerAddr, serverAddr)
 | |
| 					}
 | |
| 					if !reflect.DeepEqual(endpoints, testCase.expectedEndpoints) {
 | |
| 						t.Fatalf("endpoints: expected = %v, got = %v", testCase.expectedEndpoints, endpoints)
 | |
| 					}
 | |
| 					if setupType != testCase.expectedSetupType {
 | |
| 						t.Fatalf("setupType: expected = %v, got = %v", testCase.expectedSetupType, setupType)
 | |
| 					}
 | |
| 				}
 | |
| 			} else if testCase.expectedErr == nil {
 | |
| 				t.Fatalf("error: expected = <nil>, got = %v", err)
 | |
| 			} else if err.Error() != testCase.expectedErr.Error() {
 | |
| 				t.Fatalf("error: expected = %v, got = %v", testCase.expectedErr, err)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Tests get local peer functionality, local peer is supposed to only return one entry per minio service.
 | |
| // So it means that if you have say localhost:9000 and localhost:9001 as endpointArgs then localhost:9001
 | |
| // is considered a remote service from localhost:9000 perspective.
 | |
| func TestGetLocalPeer(t *testing.T) {
 | |
| 	tempGlobalMinioAddr := globalMinioAddr
 | |
| 	tempGlobalMinioPort := globalMinioPort
 | |
| 	defer func() {
 | |
| 		globalMinioAddr = tempGlobalMinioAddr
 | |
| 		globalMinioPort = tempGlobalMinioPort
 | |
| 	}()
 | |
| 	globalMinioAddr = ":9000"
 | |
| 	globalMinioPort = "9000"
 | |
| 
 | |
| 	testCases := []struct {
 | |
| 		endpointArgs   []string
 | |
| 		expectedResult string
 | |
| 	}{
 | |
| 		{[]string{"/d1", "/d2", "d3", "d4"}, "127.0.0.1:9000"},
 | |
| 		{[]string{"http://localhost:9000/d1", "http://localhost:9000/d2", "http://example.org:9000/d3", "http://example.com:9000/d4"},
 | |
| 			"localhost:9000"},
 | |
| 		{[]string{"http://localhost:9000/d1", "http://example.org:9000/d2", "http://example.com:9000/d3", "http://example.net:9000/d4"},
 | |
| 			"localhost:9000"},
 | |
| 		{[]string{"http://localhost:9000/d1", "http://localhost:9001/d2", "http://localhost:9002/d3", "http://localhost:9003/d4"},
 | |
| 			"localhost:9000"},
 | |
| 	}
 | |
| 
 | |
| 	for i, testCase := range testCases {
 | |
| 		endpoints, _ := NewEndpointList(testCase.endpointArgs...)
 | |
| 		if !endpoints[0].IsLocal {
 | |
| 			if err := endpoints.UpdateIsLocal(); err != nil {
 | |
| 				t.Fatalf("error: expected = <nil>, got = %v", err)
 | |
| 			}
 | |
| 		}
 | |
| 		remotePeer := GetLocalPeer(endpoints)
 | |
| 		if remotePeer != testCase.expectedResult {
 | |
| 			t.Fatalf("Test %d: expected: %v, got: %v", i+1, testCase.expectedResult, remotePeer)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetRemotePeers(t *testing.T) {
 | |
| 	tempGlobalMinioPort := globalMinioPort
 | |
| 	defer func() {
 | |
| 		globalMinioPort = tempGlobalMinioPort
 | |
| 	}()
 | |
| 	globalMinioPort = "9000"
 | |
| 
 | |
| 	testCases := []struct {
 | |
| 		endpointArgs   []string
 | |
| 		expectedResult []string
 | |
| 	}{
 | |
| 		{[]string{"/d1", "/d2", "d3", "d4"}, []string{}},
 | |
| 		{[]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"}},
 | |
| 		{[]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"}},
 | |
| 		{[]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"}},
 | |
| 		{[]string{"http://localhost:9000/d1", "http://localhost:9001/d2", "http://localhost:9002/d3", "http://localhost:9003/d4"}, []string{"localhost:9001", "localhost:9002", "localhost:9003"}},
 | |
| 	}
 | |
| 
 | |
| 	for _, testCase := range testCases {
 | |
| 		endpoints, _ := NewEndpointList(testCase.endpointArgs...)
 | |
| 		if !endpoints[0].IsLocal {
 | |
| 			if err := endpoints.UpdateIsLocal(); err != nil {
 | |
| 				t.Fatalf("error: expected = <nil>, got = %v", err)
 | |
| 			}
 | |
| 		}
 | |
| 		remotePeers := GetRemotePeers(endpoints)
 | |
| 		if !reflect.DeepEqual(remotePeers, testCase.expectedResult) {
 | |
| 			t.Fatalf("expected: %v, got: %v", testCase.expectedResult, remotePeers)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestUpdateDomainIPs(t *testing.T) {
 | |
| 	tempGlobalMinioPort := globalMinioPort
 | |
| 	defer func() {
 | |
| 		globalMinioPort = tempGlobalMinioPort
 | |
| 	}()
 | |
| 	globalMinioPort = "9000"
 | |
| 
 | |
| 	tempGlobalDomainIPs := globalDomainIPs
 | |
| 	defer func() {
 | |
| 		globalDomainIPs = tempGlobalDomainIPs
 | |
| 	}()
 | |
| 
 | |
| 	ipv4TestCases := []struct {
 | |
| 		endPoints      set.StringSet
 | |
| 		expectedResult set.StringSet
 | |
| 	}{
 | |
| 		{set.NewStringSet(), set.NewStringSet()},
 | |
| 		{set.CreateStringSet("localhost"), set.NewStringSet()},
 | |
| 		{set.CreateStringSet("localhost", "10.0.0.1"), set.CreateStringSet("10.0.0.1:9000")},
 | |
| 		{set.CreateStringSet("localhost:9001", "10.0.0.1"), set.CreateStringSet("10.0.0.1:9000")},
 | |
| 		{set.CreateStringSet("localhost", "10.0.0.1:9001"), set.CreateStringSet("10.0.0.1:9001")},
 | |
| 		{set.CreateStringSet("localhost:9000", "10.0.0.1:9001"), set.CreateStringSet("10.0.0.1:9001")},
 | |
| 
 | |
| 		{set.CreateStringSet("10.0.0.1", "10.0.0.2"), set.CreateStringSet("10.0.0.1:9000", "10.0.0.2:9000")},
 | |
| 		{set.CreateStringSet("10.0.0.1:9001", "10.0.0.2"), set.CreateStringSet("10.0.0.1:9001", "10.0.0.2:9000")},
 | |
| 		{set.CreateStringSet("10.0.0.1", "10.0.0.2:9002"), set.CreateStringSet("10.0.0.1:9000", "10.0.0.2:9002")},
 | |
| 		{set.CreateStringSet("10.0.0.1:9001", "10.0.0.2:9002"), set.CreateStringSet("10.0.0.1:9001", "10.0.0.2:9002")},
 | |
| 	}
 | |
| 
 | |
| 	for _, testCase := range ipv4TestCases {
 | |
| 		globalDomainIPs = nil
 | |
| 
 | |
| 		updateDomainIPs(testCase.endPoints)
 | |
| 
 | |
| 		if !testCase.expectedResult.Equals(globalDomainIPs) {
 | |
| 			t.Fatalf("error: expected = %s, got = %s", testCase.expectedResult, globalDomainIPs)
 | |
| 		}
 | |
| 	}
 | |
| }
 |