github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/fs/rc/internal_test.go (about)

     1  package rc
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"os"
     9  	"runtime"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  
    16  	"github.com/rclone/rclone/fs"
    17  	"github.com/rclone/rclone/fs/config/obscure"
    18  )
    19  
    20  func TestMain(m *testing.M) {
    21  	// Pretend to be rclone version if we have a version string parameter
    22  	if os.Args[len(os.Args)-1] == "version" {
    23  		fmt.Printf("rclone %s\n", fs.Version)
    24  		os.Exit(0)
    25  	}
    26  	// Pretend to error if we have an unknown command
    27  	if os.Args[len(os.Args)-1] == "unknown_command" {
    28  		fmt.Printf("rclone %s\n", fs.Version)
    29  		fmt.Fprintf(os.Stderr, "Unknown command\n")
    30  		os.Exit(1)
    31  	}
    32  	os.Exit(m.Run())
    33  }
    34  
    35  func TestInternalNoop(t *testing.T) {
    36  	call := Calls.Get("rc/noop")
    37  	assert.NotNil(t, call)
    38  	in := Params{
    39  		"String": "hello",
    40  		"Int":    42,
    41  	}
    42  	out, err := call.Fn(context.Background(), in)
    43  	require.NoError(t, err)
    44  	require.NotNil(t, out)
    45  	assert.Equal(t, in, out)
    46  }
    47  
    48  func TestInternalError(t *testing.T) {
    49  	call := Calls.Get("rc/error")
    50  	assert.NotNil(t, call)
    51  	in := Params{}
    52  	out, err := call.Fn(context.Background(), in)
    53  	require.Error(t, err)
    54  	require.Nil(t, out)
    55  }
    56  
    57  func TestInternalList(t *testing.T) {
    58  	call := Calls.Get("rc/list")
    59  	assert.NotNil(t, call)
    60  	in := Params{}
    61  	out, err := call.Fn(context.Background(), in)
    62  	require.NoError(t, err)
    63  	require.NotNil(t, out)
    64  	assert.Equal(t, Params{"commands": Calls.List()}, out)
    65  }
    66  
    67  func TestCorePid(t *testing.T) {
    68  	call := Calls.Get("core/pid")
    69  	assert.NotNil(t, call)
    70  	in := Params{}
    71  	out, err := call.Fn(context.Background(), in)
    72  	require.NoError(t, err)
    73  	require.NotNil(t, out)
    74  	pid := out["pid"]
    75  	assert.NotEqual(t, nil, pid)
    76  	_, ok := pid.(int)
    77  	assert.Equal(t, true, ok)
    78  }
    79  
    80  func TestCoreMemstats(t *testing.T) {
    81  	call := Calls.Get("core/memstats")
    82  	assert.NotNil(t, call)
    83  	in := Params{}
    84  	out, err := call.Fn(context.Background(), in)
    85  	require.NoError(t, err)
    86  	require.NotNil(t, out)
    87  	sys := out["Sys"]
    88  	assert.NotEqual(t, nil, sys)
    89  	_, ok := sys.(uint64)
    90  	assert.Equal(t, true, ok)
    91  }
    92  
    93  func TestCoreGC(t *testing.T) {
    94  	call := Calls.Get("core/gc")
    95  	assert.NotNil(t, call)
    96  	in := Params{}
    97  	out, err := call.Fn(context.Background(), in)
    98  	require.NoError(t, err)
    99  	require.Nil(t, out)
   100  	assert.Equal(t, Params(nil), out)
   101  }
   102  
   103  func TestCoreVersion(t *testing.T) {
   104  	call := Calls.Get("core/version")
   105  	assert.NotNil(t, call)
   106  	in := Params{}
   107  	out, err := call.Fn(context.Background(), in)
   108  	require.NoError(t, err)
   109  	require.NotNil(t, out)
   110  	assert.Equal(t, fs.Version, out["version"])
   111  	assert.Equal(t, runtime.GOOS, out["os"])
   112  	assert.Equal(t, runtime.GOARCH, out["arch"])
   113  	assert.Equal(t, runtime.Version(), out["goVersion"])
   114  	_ = out["isGit"].(bool)
   115  	v := out["decomposed"].([]int64)
   116  	assert.True(t, len(v) >= 2)
   117  }
   118  
   119  func TestCoreObscure(t *testing.T) {
   120  	call := Calls.Get("core/obscure")
   121  	assert.NotNil(t, call)
   122  	in := Params{
   123  		"clear": "potato",
   124  	}
   125  	out, err := call.Fn(context.Background(), in)
   126  	require.NoError(t, err)
   127  	require.NotNil(t, out)
   128  	assert.Equal(t, in["clear"], obscure.MustReveal(out["obscured"].(string)))
   129  }
   130  
   131  func TestCoreQuit(t *testing.T) {
   132  	//The call should return an error if param exitCode is not parsed to int
   133  	call := Calls.Get("core/quit")
   134  	assert.NotNil(t, call)
   135  	in := Params{
   136  		"exitCode": "potato",
   137  	}
   138  	_, err := call.Fn(context.Background(), in)
   139  	require.Error(t, err)
   140  }
   141  
   142  // core/command: Runs a raw rclone command
   143  func TestCoreCommand(t *testing.T) {
   144  	call := Calls.Get("core/command")
   145  
   146  	test := func(command string, returnType string, wantOutput string, fail bool) {
   147  		var rec = httptest.NewRecorder()
   148  		var w http.ResponseWriter = rec
   149  
   150  		in := Params{
   151  			"command":   command,
   152  			"opt":       map[string]string{},
   153  			"arg":       []string{},
   154  			"_response": w,
   155  		}
   156  		if returnType != "" {
   157  			in["returnType"] = returnType
   158  		} else {
   159  			returnType = "COMBINED_OUTPUT"
   160  		}
   161  		stream := strings.HasPrefix(returnType, "STREAM")
   162  		got, err := call.Fn(context.Background(), in)
   163  		if stream && fail {
   164  			assert.Error(t, err)
   165  		} else {
   166  			assert.NoError(t, err)
   167  		}
   168  
   169  		if !stream {
   170  			assert.Equal(t, wantOutput, got["result"])
   171  			assert.Equal(t, fail, got["error"])
   172  		} else {
   173  			assert.Equal(t, wantOutput, rec.Body.String())
   174  		}
   175  		assert.Equal(t, http.StatusOK, rec.Result().StatusCode)
   176  	}
   177  
   178  	version := fmt.Sprintf("rclone %s\n", fs.Version)
   179  	errorString := "Unknown command\n"
   180  	t.Run("OK", func(t *testing.T) {
   181  		test("version", "", version, false)
   182  	})
   183  	t.Run("Fail", func(t *testing.T) {
   184  		test("unknown_command", "", version+errorString, true)
   185  	})
   186  	t.Run("Combined", func(t *testing.T) {
   187  		test("unknown_command", "COMBINED_OUTPUT", version+errorString, true)
   188  	})
   189  	t.Run("Stderr", func(t *testing.T) {
   190  		test("unknown_command", "STREAM_ONLY_STDERR", errorString, true)
   191  	})
   192  	t.Run("Stdout", func(t *testing.T) {
   193  		test("unknown_command", "STREAM_ONLY_STDOUT", version, true)
   194  	})
   195  	t.Run("Stream", func(t *testing.T) {
   196  		test("unknown_command", "STREAM", version+errorString, true)
   197  	})
   198  }