github.com/vishnusomank/figtree@v0.1.0/overwrite_test.go (about) 1 package figtree 2 3 import ( 4 "os" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 "gopkg.in/yaml.v3" 10 ) 11 12 func init() { 13 StringifyValue = false 14 } 15 16 func TestOptionsOverwriteConfigD3(t *testing.T) { 17 opts := TestOptions{} 18 require.NoError(t, os.Chdir("d1/d2/d3")) 19 t.Cleanup(func() { 20 _ = os.Chdir("../../..") 21 }) 22 23 arr1 := []StringOption{} 24 arr1 = append(arr1, StringOption{tSrc("../overwrite.yml", 8, 5), true, "d2arr1val1"}) 25 arr1 = append(arr1, StringOption{tSrc("../overwrite.yml", 9, 5), true, "d2arr1val2"}) 26 27 expected := TestOptions{ 28 String1: StringOption{tSrc("../overwrite.yml", 6, 7), true, "d2str1val1"}, 29 LeaveEmpty: StringOption{}, 30 Array1: arr1, 31 Map1: map[string]StringOption{ 32 "key0": {tSrc("../../overwrite.yml", 11, 9), true, "d1map1val0"}, 33 "key1": {tSrc("../../overwrite.yml", 12, 9), true, "d1map1val1"}, 34 }, 35 Int1: IntOption{tSrc("../../overwrite.yml", 13, 7), true, 111}, 36 Float1: Float32Option{tSrc("../../overwrite.yml", 14, 9), true, 1.11}, 37 Bool1: BoolOption{tSrc("../overwrite.yml", 15, 8), true, false}, 38 } 39 40 fig := newFigTreeFromEnv() 41 err := fig.LoadAllConfigs("overwrite.yml", &opts) 42 require.NoError(t, err) 43 require.Exactly(t, expected, opts) 44 } 45 46 func TestOptionsOverwriteConfigD2(t *testing.T) { 47 opts := TestOptions{} 48 require.NoError(t, os.Chdir("d1/d2")) 49 t.Cleanup(func() { 50 _ = os.Chdir("../..") 51 }) 52 53 arr1 := []StringOption{} 54 arr1 = append(arr1, StringOption{tSrc("overwrite.yml", 8, 5), true, "d2arr1val1"}) 55 arr1 = append(arr1, StringOption{tSrc("overwrite.yml", 9, 5), true, "d2arr1val2"}) 56 57 expected := TestOptions{ 58 String1: StringOption{tSrc("overwrite.yml", 6, 7), true, "d2str1val1"}, 59 LeaveEmpty: StringOption{}, 60 Array1: arr1, 61 Map1: map[string]StringOption{ 62 "key0": {tSrc("../overwrite.yml", 11, 9), true, "d1map1val0"}, 63 "key1": {tSrc("../overwrite.yml", 12, 9), true, "d1map1val1"}, 64 }, 65 Int1: IntOption{tSrc("../overwrite.yml", 13, 7), true, 111}, 66 Float1: Float32Option{tSrc("../overwrite.yml", 14, 9), true, 1.11}, 67 Bool1: BoolOption{tSrc("overwrite.yml", 15, 8), true, false}, 68 } 69 70 fig := newFigTreeFromEnv() 71 err := fig.LoadAllConfigs("overwrite.yml", &opts) 72 assert.NoError(t, err) 73 assert.Exactly(t, expected, opts) 74 } 75 76 func TestBuiltinOverwriteConfigD3(t *testing.T) { 77 opts := TestBuiltin{} 78 require.NoError(t, os.Chdir("d1/d2/d3")) 79 t.Cleanup(func() { 80 _ = os.Chdir("../../..") 81 }) 82 83 arr1 := []string{} 84 arr1 = append(arr1, "d2arr1val1") 85 arr1 = append(arr1, "d2arr1val2") 86 87 expected := TestBuiltin{ 88 String1: "d2str1val1", 89 LeaveEmpty: "", 90 Array1: arr1, 91 Map1: map[string]string{ 92 "key0": "d1map1val0", 93 "key1": "d1map1val1", 94 }, 95 Int1: 111, 96 Float1: 1.11, 97 Bool1: false, 98 } 99 100 fig := newFigTreeFromEnv() 101 err := fig.LoadAllConfigs("overwrite.yml", &opts) 102 assert.NoError(t, err) 103 assert.Exactly(t, expected, opts) 104 } 105 106 func TestBuiltinOverwriteConfigD2(t *testing.T) { 107 opts := TestBuiltin{} 108 require.NoError(t, os.Chdir("d1/d2")) 109 t.Cleanup(func() { 110 _ = os.Chdir("../..") 111 }) 112 113 arr1 := []string{} 114 arr1 = append(arr1, "d2arr1val1") 115 arr1 = append(arr1, "d2arr1val2") 116 117 expected := TestBuiltin{ 118 String1: "d2str1val1", 119 LeaveEmpty: "", 120 Array1: arr1, 121 Map1: map[string]string{ 122 "key0": "d1map1val0", 123 "key1": "d1map1val1", 124 }, 125 Int1: 111, 126 Float1: 1.11, 127 Bool1: false, 128 } 129 130 fig := newFigTreeFromEnv() 131 err := fig.LoadAllConfigs("overwrite.yml", &opts) 132 assert.NoError(t, err) 133 assert.Exactly(t, expected, opts) 134 } 135 136 type TestArray struct { 137 IntArr [2]int `yaml:"intArr"` 138 PartialInt [2]int `yaml:"partialInt"` 139 TooManyInt [2]int `yaml:"tooManyInt"` 140 StrArr [2]string `yaml:"strArr"` 141 ToOverwrite [2]string `yaml:"toOverwrite"` 142 } 143 144 func TestBuiltinOverwriteArrayD2(t *testing.T) { 145 opts := TestArray{} 146 require.NoError(t, os.Chdir("d1/d2")) 147 t.Cleanup(func() { 148 _ = os.Chdir("../..") 149 }) 150 151 expected := TestArray{ 152 IntArr: [2]int{1, 2}, 153 PartialInt: [2]int{1, 0}, 154 TooManyInt: [2]int{1, 2}, 155 StrArr: [2]string{"abc", "def"}, 156 ToOverwrite: [2]string{"c", "d"}, 157 } 158 159 fig := newFigTreeFromEnv() 160 err := fig.LoadAllConfigs("array.yml", &opts) 161 assert.NoError(t, err) 162 assert.Exactly(t, expected, opts) 163 } 164 165 type TestOptionsArray struct { 166 IntArr [2]IntOption `yaml:"intArr"` 167 PartialInt [2]IntOption `yaml:"partialInt"` 168 TooManyInt [2]IntOption `yaml:"tooManyInt"` 169 StrArr [2]StringOption `yaml:"strArr"` 170 ToOverwrite [2]StringOption `yaml:"toOverwrite"` 171 } 172 173 func TestOptionsOverwriteArrayD2(t *testing.T) { 174 opts := TestOptionsArray{} 175 require.NoError(t, os.Chdir("d1/d2")) 176 t.Cleanup(func() { 177 _ = os.Chdir("../..") 178 }) 179 180 expected := TestOptionsArray{ 181 IntArr: [2]IntOption{ 182 {tSrc("array.yml", 1, 10), true, 1}, 183 {tSrc("array.yml", 1, 12), true, 2}, 184 }, 185 PartialInt: [2]IntOption{ 186 {tSrc("array.yml", 2, 14), true, 1}, 187 {NewSource(""), false, 0}, 188 }, 189 TooManyInt: [2]IntOption{ 190 {tSrc("array.yml", 3, 14), true, 1}, 191 {tSrc("array.yml", 3, 16), true, 2}, 192 }, 193 StrArr: [2]StringOption{ 194 {tSrc("array.yml", 4, 10), true, "abc"}, 195 {tSrc("array.yml", 4, 15), true, "def"}, 196 }, 197 ToOverwrite: [2]StringOption{ 198 {tSrc("../array.yml", 5, 15), true, "c"}, 199 {tSrc("../array.yml", 5, 17), true, "d"}, 200 }, 201 } 202 203 fig := newFigTreeFromEnv() 204 err := fig.LoadAllConfigs("array.yml", &opts) 205 assert.NoError(t, err) 206 assert.Exactly(t, expected, opts) 207 } 208 209 // auto-upgrade: 210 // enabled: true 211 212 func TestOverwritePartialStruct(t *testing.T) { 213 type MyStruct struct { 214 A StringOption `yaml:"a"` 215 B BoolOption `yaml:"b"` 216 } 217 type data struct { 218 MyStruct MyStruct `yaml:"my-struct"` 219 } 220 configs := []struct { 221 Name string 222 Body string 223 }{{ 224 Name: "test", 225 Body: ` 226 my-struct: 227 b: true 228 `, 229 }, { 230 Name: "../test", 231 Body: ` 232 config: {overwrite: [my-struct]} 233 my-struct: 234 b: false 235 a: foo 236 `, 237 }} 238 expected := data{ 239 MyStruct: MyStruct{ 240 A: StringOption{tSrc("../test", 5, 6), true, "foo"}, 241 B: BoolOption{tSrc("../test", 4, 6), true, false}, 242 }, 243 } 244 sources := []ConfigSource{} 245 for _, c := range configs { 246 var node yaml.Node 247 err := yaml.Unmarshal([]byte(c.Body), &node) 248 require.NoError(t, err) 249 sources = append(sources, ConfigSource{ 250 Config: &node, 251 Filename: c.Name, 252 }) 253 } 254 fig := newFigTreeFromEnv() 255 got := data{} 256 err := fig.LoadAllConfigSources(sources, &got) 257 require.NoError(t, err) 258 require.Equal(t, expected, got) 259 } 260 261 func TestOverwriteNil(t *testing.T) { 262 type MyStruct struct { 263 A StringOption `yaml:"a"` 264 B BoolOption `yaml:"b"` 265 } 266 type data struct { 267 MyStruct MyStruct `yaml:"my-struct"` 268 } 269 config := ` 270 config: {overwrite: [my-struct]} 271 my-struct: 272 ` 273 expected := data{ 274 MyStruct: MyStruct{ 275 A: StringOption{}, 276 B: BoolOption{}, 277 }, 278 } 279 var node yaml.Node 280 err := yaml.Unmarshal([]byte(config), &node) 281 require.NoError(t, err) 282 fig := newFigTreeFromEnv() 283 got := data{} 284 err = fig.LoadConfigSource(&node, "test", &got) 285 require.NoError(t, err) 286 require.Equal(t, expected, got) 287 }