1// Copyright 2018 Frank Schroeder. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package properties 6 7import ( 8 "fmt" 9 "io/ioutil" 10 "net/http" 11 "net/http/httptest" 12 "os" 13 "strings" 14 "testing" 15 16 "github.com/magiconair/properties/assert" 17) 18 19func TestEncoding(t *testing.T) { 20 if got, want := utf8Default, Encoding(0); got != want { 21 t.Fatalf("got encoding %d want %d", got, want) 22 } 23 if got, want := UTF8, Encoding(1); got != want { 24 t.Fatalf("got encoding %d want %d", got, want) 25 } 26 if got, want := ISO_8859_1, Encoding(2); got != want { 27 t.Fatalf("got encoding %d want %d", got, want) 28 } 29} 30 31func TestLoadFailsWithNotExistingFile(t *testing.T) { 32 _, err := LoadFile("doesnotexist.properties", ISO_8859_1) 33 assert.Equal(t, err != nil, true, "") 34 assert.Matches(t, err.Error(), "open.*no such file or directory") 35} 36 37func TestLoadFilesFailsOnNotExistingFile(t *testing.T) { 38 _, err := LoadFile("doesnotexist.properties", ISO_8859_1) 39 assert.Equal(t, err != nil, true, "") 40 assert.Matches(t, err.Error(), "open.*no such file or directory") 41} 42 43func TestLoadFilesDoesNotFailOnNotExistingFileAndIgnoreMissing(t *testing.T) { 44 p, err := LoadFiles([]string{"doesnotexist.properties"}, ISO_8859_1, true) 45 assert.Equal(t, err, nil) 46 assert.Equal(t, p.Len(), 0) 47} 48 49func TestLoadString(t *testing.T) { 50 x := "key=äüö" 51 p1 := MustLoadString(x) 52 p2 := must(Load([]byte(x), UTF8)) 53 assert.Equal(t, p1, p2) 54} 55 56func TestLoadMap(t *testing.T) { 57 // LoadMap does not guarantee the same import order 58 // of keys every time since map access is randomized. 59 // Therefore, we need to compare the generated maps. 60 m := map[string]string{"key": "value", "abc": "def"} 61 assert.Equal(t, LoadMap(m).Map(), m) 62} 63 64func TestLoadFile(t *testing.T) { 65 tf := make(tempFiles, 0) 66 defer tf.removeAll() 67 68 filename := tf.makeFile("key=value") 69 p := MustLoadFile(filename, ISO_8859_1) 70 71 assert.Equal(t, p.Len(), 1) 72 assertKeyValues(t, "", p, "key", "value") 73} 74 75func TestLoadFiles(t *testing.T) { 76 tf := make(tempFiles, 0) 77 defer tf.removeAll() 78 79 filename := tf.makeFile("key=value") 80 filename2 := tf.makeFile("key2=value2") 81 p := MustLoadFiles([]string{filename, filename2}, ISO_8859_1, false) 82 assertKeyValues(t, "", p, "key", "value", "key2", "value2") 83} 84 85func TestLoadExpandedFile(t *testing.T) { 86 tf := make(tempFiles, 0) 87 defer tf.removeAll() 88 89 if err := os.Setenv("_VARX", "some-value"); err != nil { 90 t.Fatal(err) 91 } 92 filename := tf.makeFilePrefix(os.Getenv("_VARX"), "key=value") 93 filename = strings.Replace(filename, os.Getenv("_VARX"), "${_VARX}", -1) 94 p := MustLoadFile(filename, ISO_8859_1) 95 assertKeyValues(t, "", p, "key", "value") 96} 97 98func TestLoadFilesAndIgnoreMissing(t *testing.T) { 99 tf := make(tempFiles, 0) 100 defer tf.removeAll() 101 102 filename := tf.makeFile("key=value") 103 filename2 := tf.makeFile("key2=value2") 104 p := MustLoadFiles([]string{filename, filename + "foo", filename2, filename2 + "foo"}, ISO_8859_1, true) 105 assertKeyValues(t, "", p, "key", "value", "key2", "value2") 106} 107 108func TestLoadURL(t *testing.T) { 109 srv := testServer() 110 defer srv.Close() 111 p := MustLoadURL(srv.URL + "/a") 112 assertKeyValues(t, "", p, "key", "value") 113} 114 115func TestLoadURLs(t *testing.T) { 116 srv := testServer() 117 defer srv.Close() 118 p := MustLoadURLs([]string{srv.URL + "/a", srv.URL + "/b"}, false) 119 assertKeyValues(t, "", p, "key", "value", "key2", "value2") 120} 121 122func TestLoadURLsAndFailMissing(t *testing.T) { 123 srv := testServer() 124 defer srv.Close() 125 p, err := LoadURLs([]string{srv.URL + "/a", srv.URL + "/c"}, false) 126 assert.Equal(t, p, (*Properties)(nil)) 127 assert.Matches(t, err.Error(), ".*returned 404.*") 128} 129 130func TestLoadURLsAndIgnoreMissing(t *testing.T) { 131 srv := testServer() 132 defer srv.Close() 133 p := MustLoadURLs([]string{srv.URL + "/a", srv.URL + "/b", srv.URL + "/c"}, true) 134 assertKeyValues(t, "", p, "key", "value", "key2", "value2") 135} 136 137func TestLoadURLEncoding(t *testing.T) { 138 srv := testServer() 139 defer srv.Close() 140 141 uris := []string{"/none", "/utf8", "/plain", "/latin1", "/iso88591"} 142 for i, uri := range uris { 143 p := MustLoadURL(srv.URL + uri) 144 assert.Equal(t, p.GetString("key", ""), "äöü", fmt.Sprintf("%d", i)) 145 } 146} 147 148func TestLoadURLFailInvalidEncoding(t *testing.T) { 149 srv := testServer() 150 defer srv.Close() 151 152 p, err := LoadURL(srv.URL + "/json") 153 assert.Equal(t, p, (*Properties)(nil)) 154 assert.Matches(t, err.Error(), ".*invalid content type.*") 155} 156 157func TestLoadAll(t *testing.T) { 158 tf := make(tempFiles, 0) 159 defer tf.removeAll() 160 161 filename := tf.makeFile("key=value") 162 filename2 := tf.makeFile("key2=value3") 163 filename3 := tf.makeFile("key=value4") 164 srv := testServer() 165 defer srv.Close() 166 p := MustLoadAll([]string{filename, filename2, srv.URL + "/a", srv.URL + "/b", filename3}, UTF8, false) 167 assertKeyValues(t, "", p, "key", "value4", "key2", "value2") 168} 169 170type tempFiles []string 171 172func (tf *tempFiles) removeAll() { 173 for _, path := range *tf { 174 err := os.Remove(path) 175 if err != nil { 176 fmt.Printf("os.Remove: %v", err) 177 } 178 } 179} 180 181func (tf *tempFiles) makeFile(data string) string { 182 return tf.makeFilePrefix("properties", data) 183} 184 185func (tf *tempFiles) makeFilePrefix(prefix, data string) string { 186 f, err := ioutil.TempFile("", prefix) 187 if err != nil { 188 panic("ioutil.TempFile: " + err.Error()) 189 } 190 191 // remember the temp file so that we can remove it later 192 *tf = append(*tf, f.Name()) 193 194 n, err := fmt.Fprint(f, data) 195 if err != nil { 196 panic("fmt.Fprintln: " + err.Error()) 197 } 198 if n != len(data) { 199 panic(fmt.Sprintf("Data size mismatch. expected=%d wrote=%d\n", len(data), n)) 200 } 201 202 err = f.Close() 203 if err != nil { 204 panic("f.Close: " + err.Error()) 205 } 206 207 return f.Name() 208} 209 210func testServer() *httptest.Server { 211 return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 212 send := func(data []byte, contentType string) { 213 w.Header().Set("Content-Type", contentType) 214 if _, err := w.Write(data); err != nil { 215 panic(err) 216 } 217 } 218 219 utf8 := []byte("key=äöü") 220 iso88591 := []byte{0x6b, 0x65, 0x79, 0x3d, 0xe4, 0xf6, 0xfc} // key=äöü 221 222 switch r.RequestURI { 223 case "/a": 224 send([]byte("key=value"), "") 225 case "/b": 226 send([]byte("key2=value2"), "") 227 case "/none": 228 send(utf8, "") 229 case "/utf8": 230 send(utf8, "text/plain; charset=utf-8") 231 case "/json": 232 send(utf8, "application/json; charset=utf-8") 233 case "/plain": 234 send(iso88591, "text/plain") 235 case "/latin1": 236 send(iso88591, "text/plain; charset=latin1") 237 case "/iso88591": 238 send(iso88591, "text/plain; charset=iso-8859-1") 239 default: 240 w.WriteHeader(404) 241 } 242 })) 243} 244