github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/config/config_test.go (about) 1 /* 2 * Copyright (C) 2019 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package config 19 20 import ( 21 "flag" 22 "os" 23 "strings" 24 "testing" 25 26 "github.com/mysteriumnetwork/node/services/datatransfer" 27 "github.com/mysteriumnetwork/node/services/dvpn" 28 "github.com/mysteriumnetwork/node/services/scraping" 29 30 "github.com/stretchr/testify/assert" 31 "github.com/urfave/cli/v2" 32 ) 33 34 // This only tests user configuration, not the merging between multiple option sources 35 func TestUserConfig_Load(t *testing.T) { 36 // given 37 configFileName := NewTempFileName(t) 38 defer os.Remove(configFileName) 39 40 toml := ` 41 [openvpn] 42 port = 31338 43 ` 44 err := os.WriteFile(configFileName, []byte(toml), 0700) 45 assert.NoError(t, err) 46 47 // when 48 cfg := NewConfig() 49 // then 50 assert.Nil(t, cfg.Get("openvpn.port")) 51 52 // when 53 err = cfg.LoadUserConfig(configFileName) 54 // then 55 assert.NoError(t, err) 56 assert.Equal(t, 31338, cfg.GetInt("openvpn.port")) 57 } 58 59 func TestUserConfig_Save(t *testing.T) { 60 // given 61 configFileName := NewTempFileName(t) 62 defer os.Remove(configFileName) 63 64 cfg := NewConfig() 65 err := cfg.LoadUserConfig(configFileName) 66 assert.NoError(t, err) 67 68 // when: app is configured with defaults + user + CLI values 69 cfg.SetDefault("openvpn.proto", "tcp") 70 cfg.SetDefault("openvpn.port", 55) 71 cfg.SetUser("openvpn.port", 22822) 72 cfg.SetCLI("openvpn.port", 40000) 73 // then: CLI values are prioritized over user over defaults 74 assert.Equal(t, "tcp", cfg.GetString("openvpn.proto")) 75 assert.Equal(t, 40000, cfg.GetInt("openvpn.port")) 76 77 // when: user configuration is saved 78 err = cfg.SaveUserConfig() 79 // then: only user configuration values are stored 80 assert.NoError(t, err) 81 tomlContent, err := os.ReadFile(configFileName) 82 assert.NoError(t, err) 83 assert.Contains(t, string(tomlContent), "port = 22822") 84 assert.NotContains(t, string(tomlContent), `proto = "tcp"`) 85 } 86 87 func NewTempFileName(t *testing.T) string { 88 file, err := os.CreateTemp("", "*") 89 assert.NoError(t, err) 90 return file.Name() 91 } 92 93 func TestConfig_ParseStringSliceFlag(t *testing.T) { 94 var tests = []struct { 95 name string 96 args string 97 defaults *cli.StringSlice 98 values []string 99 }{ 100 { 101 name: "parse single value", 102 defaults: cli.NewStringSlice("api", "broker"), 103 args: "--discovery.type broker", 104 values: []string{"broker"}, 105 }, 106 { 107 name: "parse multiple values", 108 defaults: cli.NewStringSlice("api", "broker"), 109 args: "--discovery.type api --discovery.type broker", 110 values: []string{"api", "broker"}, 111 }, 112 { 113 name: "empty args use defaults", 114 defaults: cli.NewStringSlice("api", "broker"), 115 args: "", 116 values: []string{"api", "broker"}, 117 }, 118 { 119 name: "nil default returns empty slice", 120 args: "", 121 values: nil, 122 }, 123 } 124 125 for _, tc := range tests { 126 t.Run(tc.name, func(t *testing.T) { 127 // given 128 sliceFlag := cli.StringSliceFlag{ 129 Name: "discovery.type", 130 Usage: `Proposal discovery adapter(s) separated by comma. Options: { "api", "broker", "api,broker" }`, 131 Value: tc.defaults, 132 } 133 cfg := NewConfig() 134 flagSet := flag.NewFlagSet("", flag.ContinueOnError) 135 must(t, sliceFlag.Apply(flagSet)) 136 ctx := cli.NewContext(nil, flagSet, nil) 137 must(t, flagSet.Parse(strings.Split(tc.args, " "))) 138 139 // when 140 cfg.ParseStringSliceFlag(ctx, sliceFlag) 141 value := cfg.GetStringSlice(sliceFlag.Name) 142 143 // then 144 assert.Equal(t, tc.values, value) 145 }) 146 } 147 } 148 149 // this can happen when updating config via tequilapi - json unmarshal 150 // translates json number to float64 by default if target type is interface{} 151 func TestSimilarTypeMerge(t *testing.T) { 152 // given 153 cfg := NewConfig() 154 cfg.SetDefault("openvpn.port", 1001) 155 156 // when 157 cfg.SetUser("openvpn.port", 55.00) 158 159 // then 160 assert.Equal(t, 55, cfg.GetInt("openvpn.port")) 161 162 actual, ok := cfg.GetConfig()["openvpn"] 163 assert.True(t, ok) 164 165 actual, ok = actual.(map[string]interface{})["port"] 166 assert.True(t, ok) 167 168 assert.Equal(t, 55.0, actual) 169 } 170 171 func TestUserConfig_Get(t *testing.T) { 172 cfg := NewConfig() 173 174 // when 175 cfg.SetDefault("openvpn.port", 1001) 176 // then 177 assert.Equal(t, 1001, cfg.Get("openvpn.port")) 178 179 // when 180 cfg.SetUser("openvpn.port", 1002) 181 // then 182 assert.Equal(t, 1002, cfg.Get("openvpn.port")) 183 184 // when 185 cfg.SetCLI("openvpn.port", 1003) 186 // then 187 assert.Equal(t, 1003, cfg.Get("openvpn.port")) 188 } 189 190 func TestUserConfig_GetConfig(t *testing.T) { 191 cfg := NewConfig() 192 193 // when 194 cfg.SetDefault("enabled", false) 195 cfg.SetDefault("openvpn.port", 1001) 196 // then 197 assert.Equal( 198 t, 199 map[string]interface{}{ 200 "enabled": false, 201 "openvpn": map[string]interface{}{ 202 "port": 1001, 203 }, 204 }, 205 cfg.GetConfig(), 206 ) 207 208 // when 209 cfg.SetUser("openvpn.port", 1002) 210 // then 211 assert.Equal( 212 t, 213 map[string]interface{}{ 214 "enabled": false, 215 "openvpn": map[string]interface{}{ 216 "port": 1002, 217 }, 218 }, 219 cfg.GetConfig(), 220 ) 221 222 // when 223 cfg.SetCLI("enabled", true) 224 cfg.SetCLI("openvpn.port", 1003) 225 // then 226 assert.Equal( 227 t, 228 map[string]interface{}{ 229 "enabled": true, 230 "openvpn": map[string]interface{}{ 231 "port": 1003, 232 }, 233 }, 234 cfg.GetConfig(), 235 ) 236 } 237 238 func TestHardcodedServicesNameFlagValues(t *testing.T) { 239 // importing these constants into config package create cyclic dependency 240 assert.Equal(t, strings.Join([]string{scraping.ServiceType, datatransfer.ServiceType, dvpn.ServiceType}, ","), FlagActiveServices.Value) 241 } 242 243 func must(t *testing.T, err error) { 244 assert.NoError(t, err) 245 }