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