@marcel91200 / caddy Mirror · read-only
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 01:00 UTC

master
go 403 lines 11.1 KB
Raw
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 caddyfile
16
17 import (
18 "errors"
19 "reflect"
20 "strings"
21 "testing"
22 )
23
24 func TestDispenser_Val_Next(t *testing.T) {
25 input := `host:port
26 dir1 arg1
27 dir2 arg2 arg3
28 dir3`
29 d := NewTestDispenser(input)
30
31 if val := d.Val(); val != "" {
32 t.Fatalf("Val(): Should return empty string when no token loaded; got '%s'", val)
33 }
34
35 assertNext := func(shouldLoad bool, expectedCursor int, expectedVal string) {
36 if loaded := d.Next(); loaded != shouldLoad {
37 t.Errorf("Next(): Expected %v but got %v instead (val '%s')", shouldLoad, loaded, d.Val())
38 }
39 if d.cursor != expectedCursor {
40 t.Errorf("Expected cursor to be %d, but was %d", expectedCursor, d.cursor)
41 }
42 if d.nesting != 0 {
43 t.Errorf("Nesting should be 0, was %d instead", d.nesting)
44 }
45 if val := d.Val(); val != expectedVal {
46 t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val)
47 }
48 }
49
50 assertNext(true, 0, "host:port")
51 assertNext(true, 1, "dir1")
52 assertNext(true, 2, "arg1")
53 assertNext(true, 3, "dir2")
54 assertNext(true, 4, "arg2")
55 assertNext(true, 5, "arg3")
56 assertNext(true, 6, "dir3")
57 // Note: This next test simply asserts existing behavior.
58 // If desired, we may wish to empty the token value after
59 // reading past the EOF. Open an issue if you want this change.
60 assertNext(false, 6, "dir3")
61 }
62
63 func TestDispenser_NextArg(t *testing.T) {
64 input := `dir1 arg1
65 dir2 arg2 arg3
66 dir3`
67 d := NewTestDispenser(input)
68
69 assertNext := func(shouldLoad bool, expectedVal string, expectedCursor int) {
70 if d.Next() != shouldLoad {
71 t.Errorf("Next(): Should load token but got false instead (val: '%s')", d.Val())
72 }
73 if d.cursor != expectedCursor {
74 t.Errorf("Next(): Expected cursor to be at %d, but it was %d", expectedCursor, d.cursor)
75 }
76 if val := d.Val(); val != expectedVal {
77 t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val)
78 }
79 }
80
81 assertNextArg := func(expectedVal string, loadAnother bool, expectedCursor int) {
82 if !d.NextArg() {
83 t.Error("NextArg(): Should load next argument but got false instead")
84 }
85 if d.cursor != expectedCursor {
86 t.Errorf("NextArg(): Expected cursor to be at %d, but it was %d", expectedCursor, d.cursor)
87 }
88 if val := d.Val(); val != expectedVal {
89 t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val)
90 }
91 if !loadAnother {
92 if d.NextArg() {
93 t.Fatalf("NextArg(): Should NOT load another argument, but got true instead (val: '%s')", d.Val())
94 }
95 if d.cursor != expectedCursor {
96 t.Errorf("NextArg(): Expected cursor to remain at %d, but it was %d", expectedCursor, d.cursor)
97 }
98 }
99 }
100
101 assertNext(true, "dir1", 0)
102 assertNextArg("arg1", false, 1)
103 assertNext(true, "dir2", 2)
104 assertNextArg("arg2", true, 3)
105 assertNextArg("arg3", false, 4)
106 assertNext(true, "dir3", 5)
107 assertNext(false, "dir3", 5)
108 }
109
110 func TestDispenser_NextLine(t *testing.T) {
111 input := `host:port
112 dir1 arg1
113 dir2 arg2 arg3`
114 d := NewTestDispenser(input)
115
116 assertNextLine := func(shouldLoad bool, expectedVal string, expectedCursor int) {
117 if d.NextLine() != shouldLoad {
118 t.Errorf("NextLine(): Should load token but got false instead (val: '%s')", d.Val())
119 }
120 if d.cursor != expectedCursor {
121 t.Errorf("NextLine(): Expected cursor to be %d, instead was %d", expectedCursor, d.cursor)
122 }
123 if val := d.Val(); val != expectedVal {
124 t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val)
125 }
126 }
127
128 assertNextLine(true, "host:port", 0)
129 assertNextLine(true, "dir1", 1)
130 assertNextLine(false, "dir1", 1)
131 d.Next() // arg1
132 assertNextLine(true, "dir2", 3)
133 assertNextLine(false, "dir2", 3)
134 d.Next() // arg2
135 assertNextLine(false, "arg2", 4)
136 d.Next() // arg3
137 assertNextLine(false, "arg3", 5)
138 }
139
140 func TestDispenser_NextBlock(t *testing.T) {
141 input := `foobar1 {
142 sub1 arg1
143 sub2
144 }
145 foobar2 {
146 }`
147 d := NewTestDispenser(input)
148
149 assertNextBlock := func(shouldLoad bool, expectedCursor, expectedNesting int) {
150 if loaded := d.NextBlock(0); loaded != shouldLoad {
151 t.Errorf("NextBlock(): Should return %v but got %v", shouldLoad, loaded)
152 }
153 if d.cursor != expectedCursor {
154 t.Errorf("NextBlock(): Expected cursor to be %d, was %d", expectedCursor, d.cursor)
155 }
156 if d.nesting != expectedNesting {
157 t.Errorf("NextBlock(): Nesting should be %d, not %d", expectedNesting, d.nesting)
158 }
159 }
160
161 assertNextBlock(false, -1, 0)
162 d.Next() // foobar1
163 assertNextBlock(true, 2, 1)
164 assertNextBlock(true, 3, 1)
165 assertNextBlock(true, 4, 1)
166 assertNextBlock(false, 5, 0)
167 d.Next() // foobar2
168 assertNextBlock(false, 8, 0) // empty block is as if it didn't exist
169 }
170
171 func TestDispenser_QuotedBracesAreArguments(t *testing.T) {
172 // quoted braces are literal argument text, not structural tokens
173 d := NewTestDispenser(`dir1 "{" "}" foo
174 dir2 "}" {
175 sub1 "{"
176 }`)
177
178 d.Next() // dir1
179 if d.NextBlock(0) {
180 t.Errorf("NextBlock(): quoted '{' must not open a block (val: '%s')", d.Val())
181 }
182 if args := d.RemainingArgs(); !reflect.DeepEqual(args, []string{"{", "}", "foo"}) {
183 t.Errorf(`RemainingArgs(): quoted braces should be visible as arguments, got %v`, args)
184 }
185
186 d.Next() // dir2
187 if args := d.RemainingArgs(); !reflect.DeepEqual(args, []string{"}"}) {
188 t.Errorf(`RemainingArgs(): quoted '}' should be an argument, got %v`, args)
189 }
190 if !d.NextBlock(0) || d.Val() != "sub1" {
191 t.Fatalf("NextBlock(): unquoted '{' should still open a block (val: '%s')", d.Val())
192 }
193 if args := d.RemainingArgs(); !reflect.DeepEqual(args, []string{"{"}) {
194 t.Errorf(`RemainingArgs(): quoted '{' inside block should be an argument, got %v`, args)
195 }
196 if d.NextBlock(0) || d.Nesting() != 0 {
197 t.Errorf("NextBlock(): block should have closed (nesting %d)", d.Nesting())
198 }
199 }
200
201 func TestDispenser_Args(t *testing.T) {
202 var s1, s2, s3 string
203 input := `dir1 arg1 arg2 arg3
204 dir2 arg4 arg5
205 dir3 arg6 arg7
206 dir4`
207 d := NewTestDispenser(input)
208
209 d.Next() // dir1
210
211 // As many strings as arguments
212 if all := d.Args(&s1, &s2, &s3); !all {
213 t.Error("Args(): Expected true, got false")
214 }
215 if s1 != "arg1" {
216 t.Errorf("Args(): Expected s1 to be 'arg1', got '%s'", s1)
217 }
218 if s2 != "arg2" {
219 t.Errorf("Args(): Expected s2 to be 'arg2', got '%s'", s2)
220 }
221 if s3 != "arg3" {
222 t.Errorf("Args(): Expected s3 to be 'arg3', got '%s'", s3)
223 }
224
225 d.Next() // dir2
226
227 // More strings than arguments
228 if all := d.Args(&s1, &s2, &s3); all {
229 t.Error("Args(): Expected false, got true")
230 }
231 if s1 != "arg4" {
232 t.Errorf("Args(): Expected s1 to be 'arg4', got '%s'", s1)
233 }
234 if s2 != "arg5" {
235 t.Errorf("Args(): Expected s2 to be 'arg5', got '%s'", s2)
236 }
237 if s3 != "arg3" {
238 t.Errorf("Args(): Expected s3 to be unchanged ('arg3'), instead got '%s'", s3)
239 }
240
241 // (quick cursor check just for kicks and giggles)
242 if d.cursor != 6 {
243 t.Errorf("Cursor should be 6, but is %d", d.cursor)
244 }
245
246 d.Next() // dir3
247
248 // More arguments than strings
249 if all := d.Args(&s1); !all {
250 t.Error("Args(): Expected true, got false")
251 }
252 if s1 != "arg6" {
253 t.Errorf("Args(): Expected s1 to be 'arg6', got '%s'", s1)
254 }
255
256 d.Next() // dir4
257
258 // No arguments or strings
259 if all := d.Args(); !all {
260 t.Error("Args(): Expected true, got false")
261 }
262
263 // No arguments but at least one string
264 if all := d.Args(&s1); all {
265 t.Error("Args(): Expected false, got true")
266 }
267 }
268
269 func TestDispenser_RemainingArgs(t *testing.T) {
270 input := `dir1 arg1 arg2 arg3
271 dir2 arg4 arg5
272 dir3 arg6 { arg7
273 dir4`
274 d := NewTestDispenser(input)
275
276 d.Next() // dir1
277
278 args := d.RemainingArgs()
279 if expected := []string{"arg1", "arg2", "arg3"}; !reflect.DeepEqual(args, expected) {
280 t.Errorf("RemainingArgs(): Expected %v, got %v", expected, args)
281 }
282
283 d.Next() // dir2
284
285 args = d.RemainingArgs()
286 if expected := []string{"arg4", "arg5"}; !reflect.DeepEqual(args, expected) {
287 t.Errorf("RemainingArgs(): Expected %v, got %v", expected, args)
288 }
289
290 d.Next() // dir3
291
292 args = d.RemainingArgs()
293 if expected := []string{"arg6"}; !reflect.DeepEqual(args, expected) {
294 t.Errorf("RemainingArgs(): Expected %v, got %v", expected, args)
295 }
296
297 d.Next() // {
298 d.Next() // arg7
299 d.Next() // dir4
300
301 args = d.RemainingArgs()
302 if len(args) != 0 {
303 t.Errorf("RemainingArgs(): Expected %v, got %v", []string{}, args)
304 }
305 }
306
307 func TestDispenser_RemainingArgsAsTokens(t *testing.T) {
308 input := `dir1 arg1 arg2 arg3
309 dir2 arg4 arg5
310 dir3 arg6 { arg7
311 dir4`
312 d := NewTestDispenser(input)
313
314 d.Next() // dir1
315
316 args := d.RemainingArgsAsTokens()
317
318 tokenTexts := make([]string, 0, len(args))
319 for _, arg := range args {
320 tokenTexts = append(tokenTexts, arg.Text)
321 }
322
323 if expected := []string{"arg1", "arg2", "arg3"}; !reflect.DeepEqual(tokenTexts, expected) {
324 t.Errorf("RemainingArgsAsTokens(): Expected %v, got %v", expected, tokenTexts)
325 }
326
327 d.Next() // dir2
328
329 args = d.RemainingArgsAsTokens()
330
331 tokenTexts = tokenTexts[:0]
332 for _, arg := range args {
333 tokenTexts = append(tokenTexts, arg.Text)
334 }
335
336 if expected := []string{"arg4", "arg5"}; !reflect.DeepEqual(tokenTexts, expected) {
337 t.Errorf("RemainingArgsAsTokens(): Expected %v, got %v", expected, tokenTexts)
338 }
339
340 d.Next() // dir3
341
342 args = d.RemainingArgsAsTokens()
343 tokenTexts = tokenTexts[:0]
344 for _, arg := range args {
345 tokenTexts = append(tokenTexts, arg.Text)
346 }
347
348 if expected := []string{"arg6"}; !reflect.DeepEqual(tokenTexts, expected) {
349 t.Errorf("RemainingArgsAsTokens(): Expected %v, got %v", expected, tokenTexts)
350 }
351
352 d.Next() // {
353 d.Next() // arg7
354 d.Next() // dir4
355
356 args = d.RemainingArgsAsTokens()
357 tokenTexts = tokenTexts[:0]
358 for _, arg := range args {
359 tokenTexts = append(tokenTexts, arg.Text)
360 }
361
362 if len(args) != 0 {
363 t.Errorf("RemainingArgsAsTokens(): Expected %v, got %v", []string{}, tokenTexts)
364 }
365 }
366
367 func TestDispenser_ArgErr_Err(t *testing.T) {
368 input := `dir1 {
369 }
370 dir2 arg1 arg2`
371 d := NewTestDispenser(input)
372
373 d.cursor = 1 // {
374
375 if err := d.ArgErr(); err == nil || !strings.Contains(err.Error(), "{") {
376 t.Errorf("ArgErr(): Expected an error message with { in it, but got '%v'", err)
377 }
378
379 d.cursor = 5 // arg2
380
381 if err := d.ArgErr(); err == nil || !strings.Contains(err.Error(), "arg2") {
382 t.Errorf("ArgErr(): Expected an error message with 'arg2' in it; got '%v'", err)
383 }
384
385 err := d.Err("foobar")
386 if err == nil {
387 t.Fatalf("Err(): Expected an error, got nil")
388 }
389
390 if !strings.Contains(err.Error(), "Testfile:3") {
391 t.Errorf("Expected error message with filename:line in it; got '%v'", err)
392 }
393
394 if !strings.Contains(err.Error(), "foobar") {
395 t.Errorf("Expected error message with custom message in it ('foobar'); got '%v'", err)
396 }
397
398 ErrBarIsFull := errors.New("bar is full")
399 bookingError := d.Errf("unable to reserve: %w", ErrBarIsFull)
400 if !errors.Is(bookingError, ErrBarIsFull) {
401 t.Errorf("Errf(): should be able to unwrap the error chain")
402 }
403 }