1
+// Copyright 2015 Matthew Holt and The Caddy Authors
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+// http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+// See the License for the specific language governing permissions and
13
+// limitations under the License.
14
+
15
+package caddy
16
+
17
+import (
18
+ "fmt"
19
+ "os"
20
+ "path/filepath"
21
+ "runtime"
22
+ "testing"
23
+)
24
+
25
+func fakeReplacer() replacer {
26
+ return replacer{
27
+ providers: make([]ReplacementFunc, 0),
28
+ static: make(map[string]string),
29
+ }
30
+}
31
+
32
+// Tests the Set method by setting some variables and check if they are added to static
33
+func TestReplacerSet(t *testing.T) {
34
+ rep := fakeReplacer()
35
+
36
+ for _, tc := range []struct {
37
+ variable string
38
+ value string
39
+ }{
40
+ {
41
+ variable: "test1",
42
+ value: "val1",
43
+ },
44
+ {
45
+ variable: "asdf",
46
+ value: "123",
47
+ },
48
+ {
49
+ variable: "äöü",
50
+ value: "öö_äü",
51
+ },
52
+ {
53
+ variable: "with space",
54
+ value: "space value",
55
+ },
56
+ {
57
+ variable: "1",
58
+ value: "test-123",
59
+ },
60
+ {
61
+ variable: "mySuper_IP",
62
+ value: "1.2.3.4",
63
+ },
64
+ {
65
+ variable: "testEmpty",
66
+ value: "",
67
+ },
68
+ } {
69
+ rep.Set(tc.variable, tc.value)
70
+
71
+ // test if key is added
72
+ if val, ok := rep.static[tc.variable]; ok {
73
+ if val != tc.value {
74
+ t.Errorf("Expected value '%s' for key '%s' got '%s'", tc.value, tc.variable, val)
75
+ }
76
+ } else {
77
+ t.Errorf("Expected existing key '%s' found nothing", tc.variable)
78
+ }
79
+ }
80
+
81
+ // test if all keys are still there (by length)
82
+ length := len(rep.static)
83
+ if len(rep.static) != 7 {
84
+ t.Errorf("Expected length '%v' got '%v'", 7, length)
85
+ }
86
+}
87
+
88
+func TestReplacerReplaceAll(t *testing.T) {
89
+ rep := replacer{
90
+ providers: []ReplacementFunc{
91
+ // split our possible vars to two functions (to test if both functions are called)
92
+ func(key string) (val string, ok bool) {
93
+ switch key {
94
+ case "test1":
95
+ return "val1", true
96
+ case "asdf":
97
+ return "123", true
98
+ case "äöü":
99
+ return "öö_äü", true
100
+ case "with space":
101
+ return "space value", true
102
+ default:
103
+ return "NOOO", false
104
+ }
105
+ },
106
+ func(key string) (val string, ok bool) {
107
+ switch key {
108
+ case "1":
109
+ return "test-123", true
110
+ case "mySuper_IP":
111
+ return "1.2.3.4", true
112
+ case "testEmpty":
113
+ return "", true
114
+ default:
115
+ return "NOOO", false
116
+ }
117
+ },
118
+ },
119
+ }
120
+
121
+ for _, tc := range []struct {
122
+ testInput string
123
+ expected string
124
+ }{
125
+ {
126
+ // test vars without space
127
+ testInput: "{test1}{asdf}{äöü}{1}{with space}{mySuper_IP}",
128
+ expected: "val1123öö_äütest-123space value1.2.3.4",
129
+ },
130
+ {
131
+ // test vars with space
132
+ testInput: "{test1} {asdf} {äöü} {1} {with space} {mySuper_IP} ",
133
+ expected: "val1 123 öö_äü test-123 space value 1.2.3.4 ",
134
+ },
135
+ {
136
+ // test with empty val
137
+ testInput: "{test1} {testEmpty} {asdf} {1} ",
138
+ expected: "val1 EMPTY 123 test-123 ",
139
+ },
140
+ {
141
+ // test vars with not finished placeholders
142
+ testInput: "{te{test1}{as{{df{1}",
143
+ expected: "{teval1{as{{dftest-123",
144
+ },
145
+ {
146
+ // test with non existing vars
147
+ testInput: "{test1} {nope} {1} ",
148
+ expected: "val1 {nope} test-123 ",
149
+ },
150
+ } {
151
+ actual := rep.ReplaceAll(tc.testInput, "EMPTY")
152
+
153
+ // test if all are replaced as expected
154
+ if actual != tc.expected {
155
+ t.Errorf("Expected '%s' got '%s' for '%s'", tc.expected, actual, tc.testInput)
156
+ }
157
+ }
158
+}
159
+
160
+func TestReplacerDelete(t *testing.T) {
161
+ rep := replacer{
162
+ static: map[string]string{
163
+ "key1": "val1",
164
+ "key2": "val2",
165
+ "key3": "val3",
166
+ "key4": "val4",
167
+ },
168
+ }
169
+
170
+ startLen := len(rep.static)
171
+
172
+ toDel := []string{
173
+ "key2", "key4",
174
+ }
175
+
176
+ for _, key := range toDel {
177
+ rep.Delete(key)
178
+
179
+ // test if key is removed from static map
180
+ if _, ok := rep.static[key]; ok {
181
+ t.Errorf("Expected '%s' to be removed. It is still in static map.", key)
182
+ }
183
+ }
184
+
185
+ // check if static slice is smaller
186
+ expected := startLen - len(toDel)
187
+ actual := len(rep.static)
188
+ if len(rep.static) != expected {
189
+ t.Errorf("Expected length '%v' got length '%v'", expected, actual)
190
+ }
191
+}
192
+
193
+func TestReplacerMap(t *testing.T) {
194
+ rep := fakeReplacer()
195
+
196
+ for i, tc := range []ReplacementFunc{
197
+ func(key string) (val string, ok bool) {
198
+ return "", false
199
+ },
200
+ func(key string) (val string, ok bool) {
201
+ return "", false
202
+ },
203
+ } {
204
+ rep.Map(tc)
205
+
206
+ // test if function (which listens on specific key) is added by checking length
207
+ if len(rep.providers) == i+1 {
208
+ // check if the last function is the one we just added
209
+ pTc := fmt.Sprintf("%p", tc)
210
+ pRep := fmt.Sprintf("%p", rep.providers[i])
211
+ if pRep != pTc {
212
+ t.Errorf("Expected func pointer '%s' got '%s'", pTc, pRep)
213
+ }
214
+ } else {
215
+ t.Errorf("Expected providers length '%v' got length '%v'", i+1, len(rep.providers))
216
+ }
217
+ }
218
+}
219
+
220
+func TestReplacerNew(t *testing.T) {
221
+ var tc = NewReplacer()
222
+
223
+ rep, ok := tc.(*replacer)
224
+ if ok {
225
+ if len(rep.providers) != 2 {
226
+ t.Errorf("Expected providers length '%v' got length '%v'", 2, len(rep.providers))
227
+ } else {
228
+ // test if default global replacements are added as the first provider
229
+ hostname, _ := os.Hostname()
230
+ os.Setenv("CADDY_REPLACER_TEST", "envtest")
231
+
232
+ for _, tc := range []struct {
233
+ variable string
234
+ value string
235
+ }{
236
+ {
237
+ variable: "system.hostname",
238
+ value: hostname,
239
+ },
240
+ {
241
+ variable: "system.slash",
242
+ value: string(filepath.Separator),
243
+ },
244
+ {
245
+ variable: "system.os",
246
+ value: runtime.GOOS,
247
+ },
248
+ {
249
+ variable: "system.arch",
250
+ value: runtime.GOARCH,
251
+ },
252
+ {
253
+ variable: "env.CADDY_REPLACER_TEST",
254
+ value: "envtest",
255
+ },
256
+ } {
257
+ if val, ok := rep.providers[0](tc.variable); ok {
258
+ if val != tc.value {
259
+ t.Errorf("Expected value '%s' for key '%s' got '%s'", tc.value, tc.variable, val)
260
+ }
261
+ } else {
262
+ t.Errorf("Expected key '%s' to be recognized by first provider", tc.variable)
263
+ }
264
+ }
265
+ }
266
+ } else {
267
+ t.Errorf("Expected type of replacer %T got %T ", &replacer{}, tc)
268
+ }
269
+}