/ *
* 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 (
"fmt"
"net/url"
"reflect"
"runtime"
"sort"
"strings"
"testing"
)
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" )
errMsg := ": no such host"
if runtime . GOOS == "windows" {
errMsg = ": No such host is known."
}
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 } , URLEndpointType , nil } ,
{ "http://localhost/path//" , Endpoint { URL : u1 , IsLocal : true } , URLEndpointType , nil } ,
{ "https://example.org/path" , Endpoint { URL : u2 } , URLEndpointType , nil } ,
{ "http://127.0.0.1:8080/path" , Endpoint { URL : u3 , IsLocal : true } , URLEndpointType , nil } ,
{ "http://192.168.253.200/path" , Endpoint { URL : u4 } , URLEndpointType , nil } ,
{ "" , Endpoint { } , - 1 , fmt . Errorf ( "empty or root endpoint is not supported" ) } ,
{ "/" , 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" ) } ,
{ "http://server/path" , Endpoint { } , - 1 , fmt . Errorf ( "lookup server" + errMsg ) } ,
}
for _ , testCase := range testCases {
endpoint , err := NewEndpoint ( testCase . arg )
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 {
var match bool
if strings . HasSuffix ( testCase . expectedErr . Error ( ) , errMsg ) {
match = strings . HasSuffix ( err . Error ( ) , errMsg )
} else {
match = ( testCase . expectedErr . Error ( ) == err . Error ( ) )
}
if ! match {
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 { "d1" , "d2" , "d3" , "d4" , "d5" } , fmt . Errorf ( "A total of 5 endpoints were found. For erasure mode it should be an even number between 4 and 16" ) } ,
{ [ ] 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" ) } ,
}
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
sort . Strings ( args )
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.com:10000/d4" ,
"http://example.org:10000/d3" ,
}
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.com:10000/d4" ,
"http://example.org:10000/d3" ,
}
case2URLs , case2LocalFlags := getExpectedEndpoints ( args , "http://" + nonLoopBackIP + ":10000/" )
case3Endpoint1 := "http://" + nonLoopBackIP + "/d1"
args = [ ] string {
"http://" + nonLoopBackIP + ":80/d1" ,
"http://example.com:80/d3" ,
"http://example.net:80/d4" ,
"http://example.org:9000/d2" ,
}
case3URLs , case3LocalFlags := getExpectedEndpoints ( args , "http://" + nonLoopBackIP + ":80/" )
case4Endpoint1 := "http://" + nonLoopBackIP + "/d1"
args = [ ] string {
"http://" + nonLoopBackIP + ":9000/d1" ,
"http://example.com:9000/d3" ,
"http://example.net:9000/d4" ,
"http://example.org:9000/d2" ,
}
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 ( "missing port in address localhost" ) } ,
// 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 found for this host" ) } ,
{ ":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 found for this host" ) } ,
{ "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://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 ] } ,
Endpoint { URL : case1URLs [ 1 ] , IsLocal : case1LocalFlags [ 1 ] } ,
Endpoint { URL : case1URLs [ 2 ] , IsLocal : case1LocalFlags [ 2 ] } ,
Endpoint { URL : case1URLs [ 3 ] , IsLocal : case1LocalFlags [ 3 ] } ,
} , 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 ] } ,
Endpoint { URL : case2URLs [ 1 ] , IsLocal : case2LocalFlags [ 1 ] } ,
Endpoint { URL : case2URLs [ 2 ] , IsLocal : case2LocalFlags [ 2 ] } ,
Endpoint { URL : case2URLs [ 3 ] , IsLocal : case2LocalFlags [ 3 ] } ,
} , 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 ] } ,
Endpoint { URL : case3URLs [ 1 ] , IsLocal : case3LocalFlags [ 1 ] } ,
Endpoint { URL : case3URLs [ 2 ] , IsLocal : case3LocalFlags [ 2 ] } ,
Endpoint { URL : case3URLs [ 3 ] , IsLocal : case3LocalFlags [ 3 ] } ,
} , 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 ] } ,
Endpoint { URL : case4URLs [ 1 ] , IsLocal : case4LocalFlags [ 1 ] } ,
Endpoint { URL : case4URLs [ 2 ] , IsLocal : case4LocalFlags [ 2 ] } ,
Endpoint { URL : case4URLs [ 3 ] , IsLocal : case4LocalFlags [ 3 ] } ,
} , DistXLSetupType , nil } ,
{ ":9000" , [ ] string { case5Endpoint1 , case5Endpoint2 , case5Endpoint3 , case5Endpoint4 } , ":9000" , EndpointList {
Endpoint { URL : case5URLs [ 0 ] , IsLocal : case5LocalFlags [ 0 ] } ,
Endpoint { URL : case5URLs [ 1 ] , IsLocal : case5LocalFlags [ 1 ] } ,
Endpoint { URL : case5URLs [ 2 ] , IsLocal : case5LocalFlags [ 2 ] } ,
Endpoint { URL : case5URLs [ 3 ] , IsLocal : case5LocalFlags [ 3 ] } ,
} , 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 ] } ,
Endpoint { URL : case6URLs [ 1 ] , IsLocal : case6LocalFlags [ 1 ] } ,
Endpoint { URL : case6URLs [ 2 ] , IsLocal : case6LocalFlags [ 2 ] } ,
Endpoint { URL : case6URLs [ 3 ] , IsLocal : case6LocalFlags [ 3 ] } ,
} , DistXLSetupType , nil } ,
}
for _ , testCase := range testCases {
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 )
}
}
}
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 ... )
remotePeers := GetRemotePeers ( endpoints )
if ! reflect . DeepEqual ( remotePeers , testCase . expectedResult ) {
t . Fatalf ( "expected: %v, got: %v" , testCase . expectedResult , remotePeers )
}
}
}