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

     1  package rc
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"github.com/rclone/rclone/fs"
    15  )
    16  
    17  func TestErrParamNotFoundError(t *testing.T) {
    18  	e := ErrParamNotFound("key")
    19  	assert.Equal(t, "Didn't find key \"key\" in input", e.Error())
    20  }
    21  
    22  func TestIsErrParamNotFound(t *testing.T) {
    23  	assert.Equal(t, true, IsErrParamNotFound(ErrParamNotFound("key")))
    24  	assert.Equal(t, false, IsErrParamNotFound(nil))
    25  	assert.Equal(t, false, IsErrParamNotFound(errors.New("potato")))
    26  }
    27  
    28  func TestNotErrParamNotFound(t *testing.T) {
    29  	assert.Equal(t, false, NotErrParamNotFound(ErrParamNotFound("key")))
    30  	assert.Equal(t, false, NotErrParamNotFound(nil))
    31  	assert.Equal(t, true, NotErrParamNotFound(errors.New("potato")))
    32  }
    33  
    34  func TestIsErrParamInvalid(t *testing.T) {
    35  	e := ErrParamInvalid{errors.New("potato")}
    36  	assert.Equal(t, true, IsErrParamInvalid(e))
    37  	assert.Equal(t, false, IsErrParamInvalid(nil))
    38  	assert.Equal(t, false, IsErrParamInvalid(errors.New("potato")))
    39  }
    40  
    41  func TestReshape(t *testing.T) {
    42  	in := Params{
    43  		"String": "hello",
    44  		"Float":  4.2,
    45  	}
    46  	var out struct {
    47  		String string
    48  		Float  float64
    49  	}
    50  	require.NoError(t, Reshape(&out, in))
    51  	assert.Equal(t, "hello", out.String)
    52  	assert.Equal(t, 4.2, out.Float)
    53  	var inCopy = Params{}
    54  	require.NoError(t, Reshape(&inCopy, out))
    55  	assert.Equal(t, in, inCopy)
    56  
    57  	// Now a failure to marshal
    58  	var in2 func()
    59  	require.Error(t, Reshape(&inCopy, in2))
    60  
    61  	// Now a failure to unmarshal
    62  	require.Error(t, Reshape(&out, "string"))
    63  
    64  }
    65  
    66  func TestParamsCopy(t *testing.T) {
    67  	in := Params{
    68  		"ok":  1,
    69  		"x":   "seventeen",
    70  		"nil": nil,
    71  	}
    72  	out := in.Copy()
    73  	assert.Equal(t, in, out)
    74  	if &in == &out {
    75  		t.Error("didn't copy")
    76  	}
    77  }
    78  
    79  func TestParamsGet(t *testing.T) {
    80  	in := Params{
    81  		"ok": 1,
    82  	}
    83  	v1, e1 := in.Get("ok")
    84  	assert.NoError(t, e1)
    85  	assert.Equal(t, 1, v1)
    86  	v2, e2 := in.Get("notOK")
    87  	assert.Error(t, e2)
    88  	assert.Equal(t, nil, v2)
    89  	assert.Equal(t, ErrParamNotFound("notOK"), e2)
    90  }
    91  
    92  func TestParamsGetString(t *testing.T) {
    93  	in := Params{
    94  		"string":    "one",
    95  		"notString": 17,
    96  	}
    97  	v1, e1 := in.GetString("string")
    98  	assert.NoError(t, e1)
    99  	assert.Equal(t, "one", v1)
   100  	v2, e2 := in.GetString("notOK")
   101  	assert.Error(t, e2)
   102  	assert.Equal(t, "", v2)
   103  	assert.Equal(t, ErrParamNotFound("notOK"), e2)
   104  	v3, e3 := in.GetString("notString")
   105  	assert.Error(t, e3)
   106  	assert.Equal(t, "", v3)
   107  	assert.Equal(t, true, IsErrParamInvalid(e3), e3.Error())
   108  }
   109  
   110  func TestParamsGetInt64(t *testing.T) {
   111  	for _, test := range []struct {
   112  		value     interface{}
   113  		result    int64
   114  		errString string
   115  	}{
   116  		{"123", 123, ""},
   117  		{"123x", 0, "couldn't parse"},
   118  		{int(12), 12, ""},
   119  		{int64(13), 13, ""},
   120  		{float64(14), 14, ""},
   121  		{float64(9.3e18), 0, "overflows int64"},
   122  		{float64(-9.3e18), 0, "overflows int64"},
   123  	} {
   124  		t.Run(fmt.Sprintf("%T=%v", test.value, test.value), func(t *testing.T) {
   125  			in := Params{
   126  				"key": test.value,
   127  			}
   128  			v1, e1 := in.GetInt64("key")
   129  			if test.errString == "" {
   130  				require.NoError(t, e1)
   131  				assert.Equal(t, test.result, v1)
   132  			} else {
   133  				require.NotNil(t, e1)
   134  				require.Error(t, e1)
   135  				assert.Contains(t, e1.Error(), test.errString)
   136  				assert.Equal(t, int64(0), v1)
   137  			}
   138  		})
   139  	}
   140  	in := Params{
   141  		"notInt64": []string{"a", "b"},
   142  	}
   143  	v2, e2 := in.GetInt64("notOK")
   144  	assert.Error(t, e2)
   145  	assert.Equal(t, int64(0), v2)
   146  	assert.Equal(t, ErrParamNotFound("notOK"), e2)
   147  	v3, e3 := in.GetInt64("notInt64")
   148  	assert.Error(t, e3)
   149  	assert.Equal(t, int64(0), v3)
   150  	assert.Equal(t, true, IsErrParamInvalid(e3), e3.Error())
   151  }
   152  
   153  func TestParamsGetFloat64(t *testing.T) {
   154  	for _, test := range []struct {
   155  		value     interface{}
   156  		result    float64
   157  		errString string
   158  	}{
   159  		{"123.1", 123.1, ""},
   160  		{"123x1", 0, "couldn't parse"},
   161  		{int(12), 12, ""},
   162  		{int64(13), 13, ""},
   163  		{float64(14), 14, ""},
   164  	} {
   165  		t.Run(fmt.Sprintf("%T=%v", test.value, test.value), func(t *testing.T) {
   166  			in := Params{
   167  				"key": test.value,
   168  			}
   169  			v1, e1 := in.GetFloat64("key")
   170  			if test.errString == "" {
   171  				require.NoError(t, e1)
   172  				assert.Equal(t, test.result, v1)
   173  			} else {
   174  				require.NotNil(t, e1)
   175  				require.Error(t, e1)
   176  				assert.Contains(t, e1.Error(), test.errString)
   177  				assert.Equal(t, float64(0), v1)
   178  			}
   179  		})
   180  	}
   181  	in := Params{
   182  		"notFloat64": []string{"a", "b"},
   183  	}
   184  	v2, e2 := in.GetFloat64("notOK")
   185  	assert.Error(t, e2)
   186  	assert.Equal(t, float64(0), v2)
   187  	assert.Equal(t, ErrParamNotFound("notOK"), e2)
   188  	v3, e3 := in.GetFloat64("notFloat64")
   189  	assert.Error(t, e3)
   190  	assert.Equal(t, float64(0), v3)
   191  	assert.Equal(t, true, IsErrParamInvalid(e3), e3.Error())
   192  }
   193  
   194  func TestParamsGetDuration(t *testing.T) {
   195  	for _, test := range []struct {
   196  		value     interface{}
   197  		result    time.Duration
   198  		errString string
   199  	}{
   200  		{"86400", time.Hour * 24, ""},
   201  		{"1y", time.Hour * 24 * 365, ""},
   202  		{"60", time.Minute * 1, ""},
   203  		{"0", 0, ""},
   204  		{"-45", -time.Second * 45, ""},
   205  		{"2", time.Second * 2, ""},
   206  		{"2h4m7s", time.Hour*2 + 4*time.Minute + 7*time.Second, ""},
   207  		{"3d", time.Hour * 24 * 3, ""},
   208  		{"off", time.Duration(fs.DurationOff), ""},
   209  		{"", 0, "parse duration"},
   210  		{12, 0, "expecting string"},
   211  		{"34y", time.Hour * 24 * 365 * 34, ""},
   212  		{"30d", time.Hour * 24 * 30, ""},
   213  		{"2M", time.Hour * 24 * 60, ""},
   214  		{"wrong", 0, "parse duration"},
   215  	} {
   216  		t.Run(fmt.Sprintf("%T=%v", test.value, test.value), func(t *testing.T) {
   217  			in := Params{
   218  				"key": test.value,
   219  			}
   220  			v1, e1 := in.GetDuration("key")
   221  			if test.errString == "" {
   222  				require.NoError(t, e1)
   223  				assert.Equal(t, test.result, v1)
   224  			} else {
   225  				require.NotNil(t, e1)
   226  				require.Error(t, e1)
   227  				assert.Contains(t, e1.Error(), test.errString)
   228  				assert.Equal(t, time.Duration(0), v1)
   229  			}
   230  		})
   231  	}
   232  	in := Params{
   233  		"notDuration": []string{"a", "b"},
   234  	}
   235  	v2, e2 := in.GetDuration("notOK")
   236  	assert.Error(t, e2)
   237  	assert.Equal(t, time.Duration(0), v2)
   238  	assert.Equal(t, ErrParamNotFound("notOK"), e2)
   239  	v3, e3 := in.GetDuration("notDuration")
   240  	assert.Error(t, e3)
   241  	assert.Equal(t, time.Duration(0), v3)
   242  	assert.Equal(t, true, IsErrParamInvalid(e3), e3.Error())
   243  }
   244  
   245  func TestParamsGetBool(t *testing.T) {
   246  	for _, test := range []struct {
   247  		value     interface{}
   248  		result    bool
   249  		errString string
   250  	}{
   251  		{true, true, ""},
   252  		{false, false, ""},
   253  		{"true", true, ""},
   254  		{"false", false, ""},
   255  		{"fasle", false, "couldn't parse"},
   256  		{int(12), true, ""},
   257  		{int(0), false, ""},
   258  		{int64(13), true, ""},
   259  		{int64(0), false, ""},
   260  		{float64(14), true, ""},
   261  		{float64(0), false, ""},
   262  	} {
   263  		t.Run(fmt.Sprintf("%T=%v", test.value, test.value), func(t *testing.T) {
   264  			in := Params{
   265  				"key": test.value,
   266  			}
   267  			v1, e1 := in.GetBool("key")
   268  			if test.errString == "" {
   269  				require.NoError(t, e1)
   270  				assert.Equal(t, test.result, v1)
   271  			} else {
   272  				require.NotNil(t, e1)
   273  				require.Error(t, e1)
   274  				assert.Contains(t, e1.Error(), test.errString)
   275  				assert.Equal(t, false, v1)
   276  			}
   277  		})
   278  	}
   279  	in := Params{
   280  		"notBool": []string{"a", "b"},
   281  	}
   282  	v2, e2 := Params{}.GetBool("notOK")
   283  	assert.Error(t, e2)
   284  	assert.Equal(t, false, v2)
   285  	assert.Equal(t, ErrParamNotFound("notOK"), e2)
   286  	v3, e3 := in.GetBool("notBool")
   287  	assert.Error(t, e3)
   288  	assert.Equal(t, false, v3)
   289  	assert.Equal(t, true, IsErrParamInvalid(e3), e3.Error())
   290  }
   291  
   292  func TestParamsGetStruct(t *testing.T) {
   293  	in := Params{
   294  		"struct": Params{
   295  			"String": "one",
   296  			"Float":  4.2,
   297  		},
   298  	}
   299  	var out struct {
   300  		String string
   301  		Float  float64
   302  	}
   303  	e1 := in.GetStruct("struct", &out)
   304  	assert.NoError(t, e1)
   305  	assert.Equal(t, "one", out.String)
   306  	assert.Equal(t, 4.2, out.Float)
   307  
   308  	e2 := in.GetStruct("notOK", &out)
   309  	assert.Error(t, e2)
   310  	assert.Equal(t, "one", out.String)
   311  	assert.Equal(t, 4.2, out.Float)
   312  	assert.Equal(t, ErrParamNotFound("notOK"), e2)
   313  
   314  	in["struct"] = "string"
   315  	e3 := in.GetStruct("struct", &out)
   316  	assert.Error(t, e3)
   317  	assert.Equal(t, "one", out.String)
   318  	assert.Equal(t, 4.2, out.Float)
   319  	assert.Equal(t, true, IsErrParamInvalid(e3), e3.Error())
   320  }
   321  
   322  func TestParamsGetStructString(t *testing.T) {
   323  	in := Params{
   324  		"struct": `{"String": "one", "Float": 4.2}`,
   325  	}
   326  	var out struct {
   327  		String string
   328  		Float  float64
   329  	}
   330  	e1 := in.GetStruct("struct", &out)
   331  	assert.NoError(t, e1)
   332  	assert.Equal(t, "one", out.String)
   333  	assert.Equal(t, 4.2, out.Float)
   334  }
   335  
   336  func TestParamsGetStructMissingOK(t *testing.T) {
   337  	in := Params{
   338  		"struct": Params{
   339  			"String": "one",
   340  			"Float":  4.2,
   341  		},
   342  	}
   343  	var out struct {
   344  		String string
   345  		Float  float64
   346  	}
   347  	e1 := in.GetStructMissingOK("struct", &out)
   348  	assert.NoError(t, e1)
   349  	assert.Equal(t, "one", out.String)
   350  	assert.Equal(t, 4.2, out.Float)
   351  
   352  	e2 := in.GetStructMissingOK("notOK", &out)
   353  	assert.NoError(t, e2)
   354  	assert.Equal(t, "one", out.String)
   355  	assert.Equal(t, 4.2, out.Float)
   356  
   357  	in["struct"] = "string"
   358  	e3 := in.GetStructMissingOK("struct", &out)
   359  	assert.Error(t, e3)
   360  	assert.Equal(t, "one", out.String)
   361  	assert.Equal(t, 4.2, out.Float)
   362  	assert.Equal(t, true, IsErrParamInvalid(e3), e3.Error())
   363  }
   364  
   365  func TestParamsGetHTTPRequest(t *testing.T) {
   366  	in := Params{}
   367  	req, err := in.GetHTTPRequest()
   368  	assert.Nil(t, req)
   369  	assert.Error(t, err)
   370  	assert.Equal(t, true, IsErrParamNotFound(err), err.Error())
   371  
   372  	in = Params{
   373  		"_request": 42,
   374  	}
   375  	req, err = in.GetHTTPRequest()
   376  	assert.Nil(t, req)
   377  	assert.Error(t, err)
   378  	assert.Equal(t, true, IsErrParamInvalid(err), err.Error())
   379  
   380  	r := new(http.Request)
   381  	in = Params{
   382  		"_request": r,
   383  	}
   384  	req, err = in.GetHTTPRequest()
   385  	assert.NotNil(t, req)
   386  	assert.NoError(t, err)
   387  	assert.Equal(t, r, req)
   388  }
   389  
   390  func TestParamsGetHTTPResponseWriter(t *testing.T) {
   391  	in := Params{}
   392  	wr, err := in.GetHTTPResponseWriter()
   393  	assert.Nil(t, wr)
   394  	assert.Error(t, err)
   395  	assert.Equal(t, true, IsErrParamNotFound(err), err.Error())
   396  
   397  	in = Params{
   398  		"_response": 42,
   399  	}
   400  	wr, err = in.GetHTTPResponseWriter()
   401  	assert.Nil(t, wr)
   402  	assert.Error(t, err)
   403  	assert.Equal(t, true, IsErrParamInvalid(err), err.Error())
   404  
   405  	var w http.ResponseWriter = httptest.NewRecorder()
   406  	in = Params{
   407  		"_response": w,
   408  	}
   409  	wr, err = in.GetHTTPResponseWriter()
   410  	assert.NotNil(t, wr)
   411  	assert.NoError(t, err)
   412  	assert.Equal(t, w, wr)
   413  }