github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/fs/rc/config_test.go (about) 1 package rc 2 3 import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "testing" 9 10 "github.com/rclone/rclone/fs" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func clearOptionBlock() func() { 16 oldOptionBlock := optionBlock 17 optionBlock = map[string]interface{}{} 18 return func() { 19 optionBlock = oldOptionBlock 20 } 21 } 22 23 var testOptions = struct { 24 String string 25 Int int 26 }{ 27 String: "hello", 28 Int: 42, 29 } 30 31 func TestAddOption(t *testing.T) { 32 defer clearOptionBlock()() 33 assert.Equal(t, len(optionBlock), 0) 34 AddOption("potato", &testOptions) 35 assert.Equal(t, len(optionBlock), 1) 36 assert.Equal(t, len(optionReload), 0) 37 assert.Equal(t, &testOptions, optionBlock["potato"]) 38 } 39 40 func TestAddOptionReload(t *testing.T) { 41 defer clearOptionBlock()() 42 assert.Equal(t, len(optionBlock), 0) 43 reload := func(ctx context.Context) error { return nil } 44 AddOptionReload("potato", &testOptions, reload) 45 assert.Equal(t, len(optionBlock), 1) 46 assert.Equal(t, len(optionReload), 1) 47 assert.Equal(t, &testOptions, optionBlock["potato"]) 48 assert.Equal(t, fmt.Sprintf("%p", reload), fmt.Sprintf("%p", optionReload["potato"])) 49 } 50 51 func TestOptionsBlocks(t *testing.T) { 52 defer clearOptionBlock()() 53 AddOption("potato", &testOptions) 54 call := Calls.Get("options/blocks") 55 require.NotNil(t, call) 56 in := Params{} 57 out, err := call.Fn(context.Background(), in) 58 require.NoError(t, err) 59 require.NotNil(t, out) 60 assert.Equal(t, Params{"options": []string{"potato"}}, out) 61 } 62 63 func TestOptionsGet(t *testing.T) { 64 defer clearOptionBlock()() 65 AddOption("potato", &testOptions) 66 call := Calls.Get("options/get") 67 require.NotNil(t, call) 68 in := Params{} 69 out, err := call.Fn(context.Background(), in) 70 require.NoError(t, err) 71 require.NotNil(t, out) 72 assert.Equal(t, Params{"potato": &testOptions}, out) 73 } 74 75 func TestOptionsGetMarshal(t *testing.T) { 76 defer clearOptionBlock()() 77 ctx := context.Background() 78 ci := fs.GetConfig(ctx) 79 80 // Add some real options 81 AddOption("main", ci) 82 AddOption("rc", &DefaultOpt) 83 84 // get them 85 call := Calls.Get("options/get") 86 require.NotNil(t, call) 87 in := Params{} 88 out, err := call.Fn(context.Background(), in) 89 require.NoError(t, err) 90 require.NotNil(t, out) 91 92 // Check that they marshal 93 _, err = json.Marshal(out) 94 require.NoError(t, err) 95 } 96 97 func TestOptionsSet(t *testing.T) { 98 defer clearOptionBlock()() 99 var reloaded int 100 AddOptionReload("potato", &testOptions, func(ctx context.Context) error { 101 if reloaded > 0 { 102 return errors.New("error while reloading") 103 } 104 reloaded++ 105 return nil 106 }) 107 call := Calls.Get("options/set") 108 require.NotNil(t, call) 109 110 in := Params{ 111 "potato": Params{ 112 "Int": 50, 113 }, 114 } 115 out, err := call.Fn(context.Background(), in) 116 require.NoError(t, err) 117 require.Nil(t, out) 118 assert.Equal(t, 50, testOptions.Int) 119 assert.Equal(t, "hello", testOptions.String) 120 assert.Equal(t, 1, reloaded) 121 122 // error from reload 123 _, err = call.Fn(context.Background(), in) 124 require.Error(t, err) 125 assert.Contains(t, err.Error(), "error while reloading") 126 127 // unknown option block 128 in = Params{ 129 "sausage": Params{ 130 "Int": 50, 131 }, 132 } 133 _, err = call.Fn(context.Background(), in) 134 require.Error(t, err) 135 assert.Contains(t, err.Error(), "unknown option block") 136 137 // bad shape 138 in = Params{ 139 "potato": []string{"a", "b"}, 140 } 141 _, err = call.Fn(context.Background(), in) 142 require.Error(t, err) 143 assert.Contains(t, err.Error(), "failed to write options") 144 145 }