github.com/JBoudou/Itero@v0.1.7/pkg/config/config_test.go (about) 1 // Itero - Online iterative vote application 2 // Copyright (C) 2020 Joseph Boudou 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as 6 // published by the Free Software Foundation, either version 3 of the 7 // License, or (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 Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <https://www.gnu.org/licenses/>. 16 17 package config 18 19 import ( 20 "bytes" 21 "errors" 22 "fmt" 23 "os" 24 "path/filepath" 25 "testing" 26 ) 27 28 type myCompoundStruct struct { 29 IntValue int 30 StringValue string 31 FloatValue float64 32 Z string `json:"other"` 33 Array [4]int 34 } 35 36 func TestValue(t *testing.T) { 37 ReadFile(t, "config.json", 2) 38 39 const key = "object" 40 var expected = myCompoundStruct{42, "foo", 3.14, "bar", [4]int{2, 3, 5, 8}} 41 42 const keyOther = "object.other" 43 var other = myCompoundStruct{27, "flu", 2.14, "blu", [4]int{1, 3, 13, 75}} 44 45 const keyPartial = "object.partial" 46 var partial = myCompoundStruct{26, "foo", 3.14, "blu", [4]int{2, 3, 5, 8}} 47 48 t.Run("found", func(t *testing.T) { 49 var got myCompoundStruct 50 err := Value(key, &got) 51 52 if err != nil { 53 t.Fatalf("Error: %v", err) 54 } 55 if got != expected { 56 t.Errorf("Got: %v. Expect: %v", got, expected) 57 } 58 }) 59 60 t.Run("not found", func(t *testing.T) { 61 var got myCompoundStruct 62 err := Value(keyOther, &got) 63 64 if err == nil { 65 t.Fatalf("Key %s found", keyOther) 66 } 67 knf, ok := err.(KeyNotFound) 68 if !ok { 69 t.Fatalf("Wrong type for error") 70 } 71 if string(knf) != keyOther { 72 t.Fatalf("Wrong key not found. Got: %s. Expect: %s.", string(knf), keyOther) 73 } 74 }) 75 76 t.Run("or found", func(t *testing.T) { 77 var got myCompoundStruct 78 err := ValueOr(key, &got, &other) 79 80 if err != nil { 81 t.Fatalf("Error: %v", err) 82 } 83 if got != expected { 84 t.Errorf("Got: %v. Expect: %v", got, expected) 85 } 86 }) 87 88 t.Run("or not found", func(t *testing.T) { 89 var got myCompoundStruct 90 err := Value(keyOther, &got) 91 if err == nil { 92 t.Fatalf("Key %s found", keyOther) 93 } 94 95 err = ValueOr(keyOther, &got, &expected) 96 97 if err != nil { 98 t.Fatalf("Error: %v", err) 99 } 100 if got != expected { 101 t.Errorf("Got: %v. Expect: %v", got, expected) 102 } 103 err = Value(keyOther, &got) 104 if err != nil { 105 t.Fatalf("Error: %v", err) 106 } 107 if got != expected { 108 t.Errorf("Got: %v. Expect: %v", got, expected) 109 } 110 }) 111 112 t.Run("partial", func(t *testing.T) { 113 got := partial 114 err := Value(keyPartial, &got) 115 116 if err != nil { 117 t.Fatalf("Error: %v", err) 118 } 119 if got == partial { 120 t.Errorf("Unchanged") 121 } 122 if got != expected { 123 t.Errorf("Got: %v. Expect: %v", got, expected) 124 } 125 }) 126 } 127 128 func TestFindFileInParent(t *testing.T) { 129 tests := []struct { 130 name string 131 pwd string // from testdata 132 file string 133 depth int 134 expect string // from testdata 135 err error 136 }{ 137 { 138 name: "Not found", 139 pwd: "a/b/c/d", 140 file: "notfound.txt", 141 depth: 3, 142 err: os.ErrNotExist, 143 }, 144 { 145 name: "Direct", 146 pwd: "a/b/c/d", 147 file: "foo.txt", 148 depth: 3, 149 expect: "a/b/c/d", 150 }, 151 { 152 name: "Last", 153 pwd: "a/b/c/d", 154 file: "foo.cfg", 155 depth: 3, 156 expect: "a", 157 }, 158 { 159 name: "Too deep", 160 pwd: "a/b/c/d", 161 file: "foo.ini", 162 depth: 3, 163 err: os.ErrNotExist, 164 }, 165 } 166 167 for _, tt := range tests { 168 // Not parallel because CWD is per thread and thread != goroutines. 169 t.Run(tt.name, func(t *testing.T) { 170 tt.pwd = filepath.FromSlash(tt.pwd) 171 tt.expect = filepath.FromSlash(tt.expect) 172 173 expectabs, _ := filepath.Abs(filepath.Join("testdata", tt.expect)) 174 origin, _ := os.Getwd() 175 os.Chdir(filepath.Join("testdata", tt.pwd)) 176 defer os.Chdir(origin) 177 178 got, err := FindFileInParent(tt.file, tt.depth) 179 180 if tt.err == nil { 181 if err != nil { 182 t.Errorf("Got unexpected error %v.", err) 183 } else { 184 if got != tt.expect { 185 gotabs, _ := filepath.Abs(got) 186 if gotabs != expectabs { 187 gotstat, _ := os.Stat(gotabs) 188 expectstat, _ := os.Stat(expectabs) 189 if !os.SameFile(gotstat, expectstat) { 190 t.Errorf("Wrong result. Got %s. Expect %s.", got, tt.expect) 191 t.Errorf("expectabs %s.", expectabs) 192 } 193 } 194 } 195 } 196 } else { 197 if !errors.Is(err, tt.err) { 198 t.Errorf("Wrong error. Got %v. Expect %v.", err, tt.err) 199 } 200 } 201 }) 202 } 203 } 204 205 // Example // 206 207 func Example() { 208 configMap := bytes.NewBufferString(`{ 209 "Foo": 42, 210 "Bar": {"Baz": 1} 211 }`) 212 var foo int 213 var bar struct{ Baz int } 214 215 Read(configMap) 216 Value("Foo", &foo) 217 Value("Bar", &bar) 218 219 fmt.Println(foo, bar.Baz) 220 // Output: 221 // 42 1 222 }