rclone/fs/rc/config_test.go
Nick Craig-Wood 8fbb259091 rc: add options/info call to enumerate options
This also makes some fields in the Options block optional - these are
documented in rc.md
2024-07-15 11:09:54 +01:00

174 lines
4.1 KiB
Go

package rc
import (
"context"
"encoding/json"
"errors"
"fmt"
"testing"
"github.com/rclone/rclone/fs"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func clearOptionBlock() func() {
oldOptionBlock := fs.OptionsRegistry
fs.OptionsRegistry = map[string]fs.OptionsInfo{}
return func() {
fs.OptionsRegistry = oldOptionBlock
}
}
var testInfo = fs.Options{{
Name: "string",
Default: "str",
Help: "It is a string",
}, {
Name: "int",
Default: 17,
Help: "It is an int",
}}
var testOptions = struct {
String string
Int int
}{
String: "hello",
Int: 42,
}
func registerTestOptions() {
fs.RegisterGlobalOptions(fs.OptionsInfo{Name: "potato", Opt: &testOptions, Options: testInfo})
}
func registerTestOptionsReload(reload func(context.Context) error) {
fs.RegisterGlobalOptions(fs.OptionsInfo{Name: "potato", Opt: &testOptions, Options: testInfo, Reload: reload})
}
func TestAddOption(t *testing.T) {
defer clearOptionBlock()()
assert.Equal(t, len(fs.OptionsRegistry), 0)
registerTestOptions()
assert.Equal(t, len(fs.OptionsRegistry), 1)
assert.Equal(t, &testOptions, fs.OptionsRegistry["potato"].Opt)
}
func TestAddOptionReload(t *testing.T) {
defer clearOptionBlock()()
assert.Equal(t, len(fs.OptionsRegistry), 0)
reload := func(ctx context.Context) error { return nil }
registerTestOptionsReload(reload)
assert.Equal(t, len(fs.OptionsRegistry), 1)
assert.Equal(t, &testOptions, fs.OptionsRegistry["potato"].Opt)
assert.Equal(t, fmt.Sprintf("%p", reload), fmt.Sprintf("%p", fs.OptionsRegistry["potato"].Reload))
}
func TestOptionsBlocks(t *testing.T) {
defer clearOptionBlock()()
registerTestOptions()
call := Calls.Get("options/blocks")
require.NotNil(t, call)
in := Params{}
out, err := call.Fn(context.Background(), in)
require.NoError(t, err)
require.NotNil(t, out)
assert.Equal(t, Params{"options": []string{"potato"}}, out)
}
func TestOptionsGet(t *testing.T) {
defer clearOptionBlock()()
registerTestOptions()
call := Calls.Get("options/get")
require.NotNil(t, call)
in := Params{}
out, err := call.Fn(context.Background(), in)
require.NoError(t, err)
require.NotNil(t, out)
assert.Equal(t, Params{"potato": &testOptions}, out)
}
func TestOptionsGetMarshal(t *testing.T) {
defer clearOptionBlock()()
ctx := context.Background()
ci := fs.GetConfig(ctx)
// Add some real options
fs.RegisterGlobalOptions(fs.OptionsInfo{Name: "main", Opt: ci, Options: nil})
fs.RegisterGlobalOptions(fs.OptionsInfo{Name: "rc", Opt: &Opt, Options: nil})
// get them
call := Calls.Get("options/get")
require.NotNil(t, call)
in := Params{}
out, err := call.Fn(context.Background(), in)
require.NoError(t, err)
require.NotNil(t, out)
// Check that they marshal
_, err = json.Marshal(out)
require.NoError(t, err)
}
func TestOptionsInfo(t *testing.T) {
defer clearOptionBlock()()
registerTestOptions()
call := Calls.Get("options/info")
require.NotNil(t, call)
in := Params{}
out, err := call.Fn(context.Background(), in)
require.NoError(t, err)
require.NotNil(t, out)
assert.Equal(t, Params{"potato": testInfo}, out)
}
func TestOptionsSet(t *testing.T) {
defer clearOptionBlock()()
var reloaded int
registerTestOptionsReload(func(ctx context.Context) error {
if reloaded > 1 {
return errors.New("error while reloading")
}
reloaded++
return nil
})
call := Calls.Get("options/set")
require.NotNil(t, call)
in := Params{
"potato": Params{
"Int": 50,
},
}
out, err := call.Fn(context.Background(), in)
require.NoError(t, err)
require.Nil(t, out)
assert.Equal(t, 50, testOptions.Int)
assert.Equal(t, "str", testOptions.String)
assert.Equal(t, 2, reloaded)
// error from reload
_, err = call.Fn(context.Background(), in)
require.Error(t, err)
assert.Contains(t, err.Error(), "error while reloading")
// unknown option block
in = Params{
"sausage": Params{
"Int": 50,
},
}
_, err = call.Fn(context.Background(), in)
require.Error(t, err)
assert.Contains(t, err.Error(), "unknown option block")
// bad shape
in = Params{
"potato": []string{"a", "b"},
}
_, err = call.Fn(context.Background(), in)
require.Error(t, err)
assert.Contains(t, err.Error(), "failed to write options")
}