github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/config/diff_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package config 5 6 import ( 7 "testing" 8 9 "github.com/masterhung0112/hk_server/v5/model" 10 11 "github.com/stretchr/testify/require" 12 ) 13 14 func defaultConfigGen() *model.Config { 15 cfg := &model.Config{} 16 cfg.SetDefaults() 17 return cfg 18 } 19 20 func BenchmarkDiff(b *testing.B) { 21 b.Run("equal empty", func(b *testing.B) { 22 baseCfg := &model.Config{} 23 actualCfg := &model.Config{} 24 b.ResetTimer() 25 for i := 0; i < b.N; i++ { 26 _, _ = Diff(baseCfg, actualCfg) 27 } 28 }) 29 30 b.Run("equal with defaults", func(b *testing.B) { 31 baseCfg := defaultConfigGen() 32 actualCfg := defaultConfigGen() 33 b.ResetTimer() 34 for i := 0; i < b.N; i++ { 35 _, _ = Diff(baseCfg, actualCfg) 36 } 37 }) 38 39 b.Run("actual empty", func(b *testing.B) { 40 baseCfg := defaultConfigGen() 41 actualCfg := &model.Config{} 42 b.ResetTimer() 43 for i := 0; i < b.N; i++ { 44 _, _ = Diff(baseCfg, actualCfg) 45 } 46 }) 47 48 b.Run("base empty", func(b *testing.B) { 49 baseCfg := &model.Config{} 50 actualCfg := defaultConfigGen() 51 b.ResetTimer() 52 for i := 0; i < b.N; i++ { 53 _, _ = Diff(baseCfg, actualCfg) 54 } 55 }) 56 57 b.Run("some diffs", func(b *testing.B) { 58 baseCfg := defaultConfigGen() 59 actualCfg := defaultConfigGen() 60 baseCfg.ServiceSettings.SiteURL = model.NewString("http://localhost") 61 baseCfg.ServiceSettings.ReadTimeout = model.NewInt(300) 62 baseCfg.SqlSettings.QueryTimeout = model.NewInt(0) 63 actualCfg.PluginSettings.EnableUploads = nil 64 actualCfg.TeamSettings.MaxChannelsPerTeam = model.NewInt64(100000) 65 actualCfg.FeatureFlags = nil 66 actualCfg.SqlSettings.DataSourceReplicas = []string{ 67 "ds0", 68 "ds1", 69 "ds2", 70 } 71 b.ResetTimer() 72 for i := 0; i < b.N; i++ { 73 _, _ = Diff(baseCfg, actualCfg) 74 } 75 }) 76 } 77 78 func TestDiff(t *testing.T) { 79 tcs := []struct { 80 name string 81 base *model.Config 82 actual *model.Config 83 diffs ConfigDiffs 84 err string 85 }{ 86 { 87 "nil", 88 nil, 89 nil, 90 nil, 91 "input configs should not be nil", 92 }, 93 { 94 "empty", 95 &model.Config{}, 96 &model.Config{}, 97 nil, 98 "", 99 }, 100 { 101 "defaults", 102 defaultConfigGen(), 103 defaultConfigGen(), 104 nil, 105 "", 106 }, 107 { 108 "default base, actual empty", 109 defaultConfigGen(), 110 &model.Config{}, 111 ConfigDiffs{ 112 { 113 "", 114 *defaultConfigGen(), 115 model.Config{}, 116 }, 117 }, 118 "", 119 }, 120 { 121 "empty base, actual default", 122 &model.Config{}, 123 defaultConfigGen(), 124 ConfigDiffs{ 125 { 126 "", 127 model.Config{}, 128 *defaultConfigGen(), 129 }, 130 }, 131 "", 132 }, 133 { 134 "string change", 135 defaultConfigGen(), 136 func() *model.Config { 137 cfg := defaultConfigGen() 138 cfg.ServiceSettings.SiteURL = model.NewString("http://changed") 139 return cfg 140 }(), 141 ConfigDiffs{ 142 { 143 Path: "ServiceSettings.SiteURL", 144 BaseVal: *defaultConfigGen().ServiceSettings.SiteURL, 145 ActualVal: "http://changed", 146 }, 147 }, 148 "", 149 }, 150 { 151 "string nil", 152 defaultConfigGen(), 153 func() *model.Config { 154 cfg := defaultConfigGen() 155 cfg.ServiceSettings.SiteURL = nil 156 return cfg 157 }(), 158 ConfigDiffs{ 159 { 160 Path: "ServiceSettings.SiteURL", 161 BaseVal: defaultConfigGen().ServiceSettings.SiteURL, 162 ActualVal: func() *string { 163 return nil 164 }(), 165 }, 166 }, 167 "", 168 }, 169 { 170 "bool change", 171 defaultConfigGen(), 172 func() *model.Config { 173 cfg := defaultConfigGen() 174 cfg.PluginSettings.Enable = model.NewBool(!*cfg.PluginSettings.Enable) 175 return cfg 176 }(), 177 ConfigDiffs{ 178 { 179 Path: "PluginSettings.Enable", 180 BaseVal: true, 181 ActualVal: false, 182 }, 183 }, 184 "", 185 }, 186 { 187 "bool nil", 188 defaultConfigGen(), 189 func() *model.Config { 190 cfg := defaultConfigGen() 191 cfg.PluginSettings.Enable = nil 192 return cfg 193 }(), 194 ConfigDiffs{ 195 { 196 Path: "PluginSettings.Enable", 197 BaseVal: defaultConfigGen().PluginSettings.Enable, 198 ActualVal: func() *bool { 199 return nil 200 }(), 201 }, 202 }, 203 "", 204 }, 205 { 206 "int change", 207 defaultConfigGen(), 208 func() *model.Config { 209 cfg := defaultConfigGen() 210 cfg.ServiceSettings.ReadTimeout = model.NewInt(0) 211 return cfg 212 }(), 213 ConfigDiffs{ 214 { 215 Path: "ServiceSettings.ReadTimeout", 216 BaseVal: *defaultConfigGen().ServiceSettings.ReadTimeout, 217 ActualVal: 0, 218 }, 219 }, 220 "", 221 }, 222 { 223 "int nil", 224 defaultConfigGen(), 225 func() *model.Config { 226 cfg := defaultConfigGen() 227 cfg.ServiceSettings.ReadTimeout = nil 228 return cfg 229 }(), 230 ConfigDiffs{ 231 { 232 Path: "ServiceSettings.ReadTimeout", 233 BaseVal: defaultConfigGen().ServiceSettings.ReadTimeout, 234 ActualVal: func() *int { 235 return nil 236 }(), 237 }, 238 }, 239 "", 240 }, 241 { 242 "slice addition", 243 defaultConfigGen(), 244 func() *model.Config { 245 cfg := defaultConfigGen() 246 cfg.SqlSettings.DataSourceReplicas = []string{ 247 "ds0", 248 "ds1", 249 } 250 return cfg 251 }(), 252 ConfigDiffs{ 253 { 254 Path: "SqlSettings.DataSourceReplicas", 255 BaseVal: defaultConfigGen().SqlSettings.DataSourceReplicas, 256 ActualVal: []string{ 257 "ds0", 258 "ds1", 259 }, 260 }, 261 }, 262 "", 263 }, 264 { 265 "slice deletion", 266 func() *model.Config { 267 cfg := defaultConfigGen() 268 cfg.SqlSettings.DataSourceReplicas = []string{ 269 "ds0", 270 "ds1", 271 } 272 return cfg 273 }(), 274 func() *model.Config { 275 cfg := defaultConfigGen() 276 cfg.SqlSettings.DataSourceReplicas = []string{ 277 "ds0", 278 } 279 return cfg 280 }(), 281 ConfigDiffs{ 282 { 283 Path: "SqlSettings.DataSourceReplicas", 284 BaseVal: []string{ 285 "ds0", 286 "ds1", 287 }, 288 ActualVal: []string{ 289 "ds0", 290 }, 291 }, 292 }, 293 "", 294 }, 295 { 296 "slice nil", 297 func() *model.Config { 298 cfg := defaultConfigGen() 299 cfg.SqlSettings.DataSourceReplicas = []string{ 300 "ds0", 301 "ds1", 302 } 303 return cfg 304 }(), 305 func() *model.Config { 306 cfg := defaultConfigGen() 307 cfg.SqlSettings.DataSourceReplicas = nil 308 return cfg 309 }(), 310 ConfigDiffs{ 311 { 312 Path: "SqlSettings.DataSourceReplicas", 313 BaseVal: []string{ 314 "ds0", 315 "ds1", 316 }, 317 ActualVal: func() []string { 318 return nil 319 }(), 320 }, 321 }, 322 "", 323 }, 324 { 325 "map change", 326 defaultConfigGen(), 327 func() *model.Config { 328 cfg := defaultConfigGen() 329 cfg.PluginSettings.PluginStates["com.mattermost.nps"] = &model.PluginState{ 330 Enable: !cfg.PluginSettings.PluginStates["com.mattermost.nps"].Enable, 331 } 332 return cfg 333 }(), 334 ConfigDiffs{ 335 { 336 Path: "PluginSettings.PluginStates", 337 BaseVal: defaultConfigGen().PluginSettings.PluginStates, 338 ActualVal: map[string]*model.PluginState{ 339 "com.mattermost.nps": { 340 Enable: !defaultConfigGen().PluginSettings.PluginStates["com.mattermost.nps"].Enable, 341 }, 342 }, 343 }, 344 }, 345 "", 346 }, 347 { 348 "map addition", 349 defaultConfigGen(), 350 func() *model.Config { 351 cfg := defaultConfigGen() 352 cfg.PluginSettings.PluginStates["com.mattermost.newplugin"] = &model.PluginState{ 353 Enable: true, 354 } 355 return cfg 356 }(), 357 ConfigDiffs{ 358 { 359 Path: "PluginSettings.PluginStates", 360 BaseVal: defaultConfigGen().PluginSettings.PluginStates, 361 ActualVal: map[string]*model.PluginState{ 362 "com.mattermost.nps": { 363 Enable: defaultConfigGen().PluginSettings.PluginStates["com.mattermost.nps"].Enable, 364 }, 365 "com.mattermost.newplugin": { 366 Enable: true, 367 }, 368 }, 369 }, 370 }, 371 "", 372 }, 373 { 374 "map deletion", 375 defaultConfigGen(), 376 func() *model.Config { 377 cfg := defaultConfigGen() 378 delete(cfg.PluginSettings.PluginStates, "com.mattermost.nps") 379 return cfg 380 }(), 381 ConfigDiffs{ 382 { 383 Path: "PluginSettings.PluginStates", 384 BaseVal: defaultConfigGen().PluginSettings.PluginStates, 385 ActualVal: func() interface{} { 386 return map[string]*model.PluginState{} 387 }(), 388 }, 389 }, 390 "", 391 }, 392 { 393 "map nil", 394 defaultConfigGen(), 395 func() *model.Config { 396 cfg := defaultConfigGen() 397 cfg.PluginSettings.PluginStates = nil 398 return cfg 399 }(), 400 ConfigDiffs{ 401 { 402 Path: "PluginSettings.PluginStates", 403 BaseVal: defaultConfigGen().PluginSettings.PluginStates, 404 ActualVal: func() map[string]*model.PluginState { 405 return nil 406 }(), 407 }, 408 }, 409 "", 410 }, 411 { 412 "map type change", 413 func() *model.Config { 414 cfg := defaultConfigGen() 415 cfg.PluginSettings.Plugins = map[string]map[string]interface{}{ 416 "com.mattermost.newplugin": { 417 "key": true, 418 }, 419 } 420 return cfg 421 }(), 422 func() *model.Config { 423 cfg := defaultConfigGen() 424 cfg.PluginSettings.Plugins = map[string]map[string]interface{}{ 425 "com.mattermost.newplugin": { 426 "key": "string", 427 }, 428 } 429 return cfg 430 }(), 431 ConfigDiffs{ 432 { 433 Path: "PluginSettings.Plugins", 434 BaseVal: func() interface{} { 435 return map[string]map[string]interface{}{ 436 "com.mattermost.newplugin": { 437 "key": true, 438 }, 439 } 440 }(), 441 ActualVal: func() interface{} { 442 return map[string]map[string]interface{}{ 443 "com.mattermost.newplugin": { 444 "key": "string", 445 }, 446 } 447 }(), 448 }, 449 }, 450 "", 451 }, 452 } 453 454 for _, tc := range tcs { 455 t.Run(tc.name, func(t *testing.T) { 456 diffs, err := Diff(tc.base, tc.actual) 457 if tc.err != "" { 458 require.EqualError(t, err, tc.err) 459 require.Nil(t, diffs) 460 } else { 461 require.NoError(t, err) 462 } 463 require.Equal(t, tc.diffs, diffs) 464 }) 465 } 466 }