mirror of https://github.com/minio/minio.git
				
				
				
			
		
			
				
	
	
		
			403 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			403 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Go
		
	
	
	
| /*
 | |
|  * MinIO Cloud Storage, (C) 2018 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 (
 | |
| 	"crypto/tls"
 | |
| 	"errors"
 | |
| 	"net/http"
 | |
| 	"net/http/httptest"
 | |
| 	"reflect"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	xrpc "github.com/minio/minio/cmd/rpc"
 | |
| 	xnet "github.com/minio/minio/pkg/net"
 | |
| )
 | |
| 
 | |
| func TestAuthArgsAuthenticate(t *testing.T) {
 | |
| 	tmpGlobalServerConfig := globalServerConfig
 | |
| 	defer func() {
 | |
| 		globalServerConfig = tmpGlobalServerConfig
 | |
| 	}()
 | |
| 	globalServerConfig = newServerConfig()
 | |
| 
 | |
| 	case1Args := AuthArgs{
 | |
| 		Token:       newAuthToken(),
 | |
| 		RPCVersion:  globalRPCAPIVersion,
 | |
| 		RequestTime: UTCNow(),
 | |
| 	}
 | |
| 
 | |
| 	case2Args := AuthArgs{
 | |
| 		Token:       newAuthToken(),
 | |
| 		RPCVersion:  globalRPCAPIVersion,
 | |
| 		RequestTime: UTCNow().Add(15 * time.Minute),
 | |
| 	}
 | |
| 
 | |
| 	case3Args := AuthArgs{
 | |
| 		Token:       newAuthToken(),
 | |
| 		RPCVersion:  globalRPCAPIVersion,
 | |
| 		RequestTime: UTCNow().Add(-16 * time.Minute),
 | |
| 	}
 | |
| 
 | |
| 	case4Args := AuthArgs{
 | |
| 		Token:       newAuthToken(),
 | |
| 		RPCVersion:  RPCVersion{99, 99, 99},
 | |
| 		RequestTime: UTCNow(),
 | |
| 	}
 | |
| 
 | |
| 	case5Args := AuthArgs{
 | |
| 		Token:       "invalid-token",
 | |
| 		RPCVersion:  globalRPCAPIVersion,
 | |
| 		RequestTime: UTCNow(),
 | |
| 	}
 | |
| 
 | |
| 	testCases := []struct {
 | |
| 		args      AuthArgs
 | |
| 		expectErr bool
 | |
| 	}{
 | |
| 		{case1Args, false},
 | |
| 		{case2Args, false},
 | |
| 		{case3Args, true},
 | |
| 		{case4Args, true},
 | |
| 		{case5Args, true},
 | |
| 	}
 | |
| 
 | |
| 	for i, testCase := range testCases {
 | |
| 		err := testCase.args.Authenticate()
 | |
| 		expectErr := (err != nil)
 | |
| 
 | |
| 		if expectErr != testCase.expectErr {
 | |
| 			t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestAuthArgsSetAuthArgs(t *testing.T) {
 | |
| 	tmpGlobalServerConfig := globalServerConfig
 | |
| 	defer func() {
 | |
| 		globalServerConfig = tmpGlobalServerConfig
 | |
| 	}()
 | |
| 	globalServerConfig = newServerConfig()
 | |
| 
 | |
| 	case1Args := AuthArgs{
 | |
| 		Token:       newAuthToken(),
 | |
| 		RPCVersion:  globalRPCAPIVersion,
 | |
| 		RequestTime: UTCNow(),
 | |
| 	}
 | |
| 
 | |
| 	case2Args := AuthArgs{
 | |
| 		Token:       newAuthToken(),
 | |
| 		RPCVersion:  globalRPCAPIVersion,
 | |
| 		RequestTime: UTCNow().Add(15 * time.Minute),
 | |
| 	}
 | |
| 
 | |
| 	testCases := []struct {
 | |
| 		args           *AuthArgs
 | |
| 		authArgs       AuthArgs
 | |
| 		expectedResult *AuthArgs
 | |
| 	}{
 | |
| 		{&AuthArgs{}, case1Args, &case1Args},
 | |
| 		{&case2Args, case1Args, &case1Args},
 | |
| 	}
 | |
| 
 | |
| 	for i, testCase := range testCases {
 | |
| 		testCase.args.SetAuthArgs(testCase.authArgs)
 | |
| 		result := testCase.args
 | |
| 
 | |
| 		if !reflect.DeepEqual(result, testCase.expectedResult) {
 | |
| 			t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestRPCClientArgsValidate(t *testing.T) {
 | |
| 	case1URL, err := xnet.ParseURL("http://localhost:12345/rpc")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 	case1Args := RPCClientArgs{
 | |
| 		NewAuthTokenFunc: newAuthToken,
 | |
| 		RPCVersion:       globalRPCAPIVersion,
 | |
| 		ServiceName:      "Arith",
 | |
| 		ServiceURL:       case1URL,
 | |
| 		TLSConfig:        nil,
 | |
| 	}
 | |
| 
 | |
| 	case2URL, err := xnet.ParseURL("https://localhost:12345/rpc")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 	case2Args := RPCClientArgs{
 | |
| 		NewAuthTokenFunc: newAuthToken,
 | |
| 		RPCVersion:       globalRPCAPIVersion,
 | |
| 		ServiceName:      "Arith",
 | |
| 		ServiceURL:       case1URL,
 | |
| 		TLSConfig:        &tls.Config{},
 | |
| 	}
 | |
| 
 | |
| 	case3Args := RPCClientArgs{
 | |
| 		NewAuthTokenFunc: nil,
 | |
| 		RPCVersion:       globalRPCAPIVersion,
 | |
| 		ServiceName:      "Arith",
 | |
| 		ServiceURL:       case1URL,
 | |
| 		TLSConfig:        &tls.Config{},
 | |
| 	}
 | |
| 
 | |
| 	case4Args := RPCClientArgs{
 | |
| 		NewAuthTokenFunc: newAuthToken,
 | |
| 		RPCVersion:       globalRPCAPIVersion,
 | |
| 		ServiceURL:       case1URL,
 | |
| 		TLSConfig:        &tls.Config{},
 | |
| 	}
 | |
| 
 | |
| 	case5URL, err := xnet.ParseURL("ftp://localhost:12345/rpc")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 	case5Args := RPCClientArgs{
 | |
| 		NewAuthTokenFunc: newAuthToken,
 | |
| 		RPCVersion:       globalRPCAPIVersion,
 | |
| 		ServiceName:      "Arith",
 | |
| 		ServiceURL:       case5URL,
 | |
| 		TLSConfig:        &tls.Config{},
 | |
| 	}
 | |
| 
 | |
| 	case6URL, err := xnet.ParseURL("http://localhost:12345/rpc?location")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 	case6Args := RPCClientArgs{
 | |
| 		NewAuthTokenFunc: newAuthToken,
 | |
| 		RPCVersion:       globalRPCAPIVersion,
 | |
| 		ServiceName:      "Arith",
 | |
| 		ServiceURL:       case6URL,
 | |
| 		TLSConfig:        &tls.Config{},
 | |
| 	}
 | |
| 
 | |
| 	case7Args := RPCClientArgs{
 | |
| 		NewAuthTokenFunc: newAuthToken,
 | |
| 		RPCVersion:       globalRPCAPIVersion,
 | |
| 		ServiceName:      "Arith",
 | |
| 		ServiceURL:       case2URL,
 | |
| 		TLSConfig:        nil,
 | |
| 	}
 | |
| 
 | |
| 	testCases := []struct {
 | |
| 		args      RPCClientArgs
 | |
| 		expectErr bool
 | |
| 	}{
 | |
| 		{case1Args, false},
 | |
| 		{case2Args, false},
 | |
| 		// NewAuthTokenFunc must not be empty error.
 | |
| 		{case3Args, true},
 | |
| 		// ServiceName must not be empty.
 | |
| 		{case4Args, true},
 | |
| 		// unknown RPC URL error.
 | |
| 		{case5Args, true},
 | |
| 		// unknown RPC URL error.
 | |
| 		{case6Args, true},
 | |
| 		// tls configuration must not be empty for https url error.
 | |
| 		{case7Args, true},
 | |
| 	}
 | |
| 
 | |
| 	for i, testCase := range testCases {
 | |
| 		err := testCase.args.validate()
 | |
| 		expectErr := (err != nil)
 | |
| 
 | |
| 		if expectErr != testCase.expectErr {
 | |
| 			t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type Args struct {
 | |
| 	AuthArgs
 | |
| 	A, B int
 | |
| }
 | |
| 
 | |
| type Quotient struct {
 | |
| 	Quo, Rem int
 | |
| }
 | |
| 
 | |
| type Arith struct{}
 | |
| 
 | |
| func (t *Arith) Multiply(args *Args, reply *int) error {
 | |
| 	*reply = args.A * args.B
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (t *Arith) Divide(args *Args, quo *Quotient) error {
 | |
| 	if args.B == 0 {
 | |
| 		return errors.New("divide by zero")
 | |
| 	}
 | |
| 	quo.Quo = args.A / args.B
 | |
| 	quo.Rem = args.A % args.B
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func TestRPCClientCall(t *testing.T) {
 | |
| 	tmpGlobalServerConfig := globalServerConfig
 | |
| 	defer func() {
 | |
| 		globalServerConfig = tmpGlobalServerConfig
 | |
| 	}()
 | |
| 	globalServerConfig = newServerConfig()
 | |
| 
 | |
| 	rpcServer := xrpc.NewServer()
 | |
| 	if err := rpcServer.RegisterName("Arith", &Arith{}); err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 
 | |
| 	httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | |
| 		rpcServer.ServeHTTP(w, r)
 | |
| 	}))
 | |
| 	defer httpServer.Close()
 | |
| 
 | |
| 	url, err := xnet.ParseURL(httpServer.URL)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 	rpcClient, err := NewRPCClient(RPCClientArgs{
 | |
| 		NewAuthTokenFunc: newAuthToken,
 | |
| 		RPCVersion:       globalRPCAPIVersion,
 | |
| 		ServiceName:      "Arith",
 | |
| 		ServiceURL:       url,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 
 | |
| 	var case1Result int
 | |
| 	case1ExpectedResult := 19 * 8
 | |
| 
 | |
| 	testCases := []struct {
 | |
| 		serviceMethod  string
 | |
| 		args           *Args
 | |
| 		result         interface{}
 | |
| 		changeConfig   bool
 | |
| 		expectedResult interface{}
 | |
| 		expectErr      bool
 | |
| 	}{
 | |
| 		{"Arith.Multiply", &Args{A: 19, B: 8}, &case1Result, false, &case1ExpectedResult, false},
 | |
| 		{"Arith.Divide", &Args{A: 19, B: 8}, &Quotient{}, false, &Quotient{2, 3}, false},
 | |
| 		{"Arith.Multiply", &Args{A: 19, B: 8}, &case1Result, true, &case1ExpectedResult, false},
 | |
| 		{"Arith.Divide", &Args{A: 19, B: 8}, &Quotient{}, true, &Quotient{2, 3}, false},
 | |
| 		{"Arith.Divide", &Args{A: 19, B: 0}, &Quotient{}, false, nil, true},
 | |
| 		{"Arith.Divide", &Args{A: 19, B: 8}, &case1Result, false, nil, true},
 | |
| 	}
 | |
| 
 | |
| 	for i, testCase := range testCases {
 | |
| 		if testCase.changeConfig {
 | |
| 			globalServerConfig = newServerConfig()
 | |
| 		}
 | |
| 
 | |
| 		err := rpcClient.Call(testCase.serviceMethod, testCase.args, testCase.result)
 | |
| 		expectErr := (err != nil)
 | |
| 
 | |
| 		if expectErr != testCase.expectErr {
 | |
| 			t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
 | |
| 		}
 | |
| 
 | |
| 		if !testCase.expectErr {
 | |
| 			if !reflect.DeepEqual(testCase.result, testCase.expectedResult) {
 | |
| 				t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, testCase.result)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestRPCClientClose(t *testing.T) {
 | |
| 	tmpGlobalServerConfig := globalServerConfig
 | |
| 	defer func() {
 | |
| 		globalServerConfig = tmpGlobalServerConfig
 | |
| 	}()
 | |
| 	globalServerConfig = newServerConfig()
 | |
| 
 | |
| 	url, err := xnet.ParseURL("http://localhost:12345")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 	rpcClient, err := NewRPCClient(RPCClientArgs{
 | |
| 		NewAuthTokenFunc: newAuthToken,
 | |
| 		RPCVersion:       globalRPCAPIVersion,
 | |
| 		ServiceName:      "Arith",
 | |
| 		ServiceURL:       url,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 
 | |
| 	testCases := []struct {
 | |
| 		rpcClient *RPCClient
 | |
| 		expectErr bool
 | |
| 	}{
 | |
| 		{rpcClient, false},
 | |
| 		// Double close.
 | |
| 		{rpcClient, false},
 | |
| 	}
 | |
| 
 | |
| 	for i, testCase := range testCases {
 | |
| 		err := testCase.rpcClient.Close()
 | |
| 		expectErr := (err != nil)
 | |
| 
 | |
| 		if expectErr != testCase.expectErr {
 | |
| 			t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestRPCClientServiceURL(t *testing.T) {
 | |
| 	tmpGlobalServerConfig := globalServerConfig
 | |
| 	defer func() {
 | |
| 		globalServerConfig = tmpGlobalServerConfig
 | |
| 	}()
 | |
| 	globalServerConfig = newServerConfig()
 | |
| 
 | |
| 	url, err := xnet.ParseURL("http://localhost:12345")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 	rpcClient, err := NewRPCClient(RPCClientArgs{
 | |
| 		NewAuthTokenFunc: newAuthToken,
 | |
| 		RPCVersion:       globalRPCAPIVersion,
 | |
| 		ServiceName:      "Arith",
 | |
| 		ServiceURL:       url,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 
 | |
| 	case1Result, err := xnet.ParseURL("http://localhost:12345")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("unexpected error %v", err)
 | |
| 	}
 | |
| 	testCases := []struct {
 | |
| 		rpcClient      *RPCClient
 | |
| 		expectedResult *xnet.URL
 | |
| 	}{
 | |
| 		{rpcClient, case1Result},
 | |
| 	}
 | |
| 
 | |
| 	for i, testCase := range testCases {
 | |
| 		result := testCase.rpcClient.ServiceURL()
 | |
| 
 | |
| 		if !reflect.DeepEqual(result, testCase.expectedResult) {
 | |
| 			t.Fatalf("case %v: expected: %v, got: %v", i+1, testCase.expectedResult, result)
 | |
| 		}
 | |
| 	}
 | |
| }
 |