@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 120 lines 4.57 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 "bytes"
19 "testing"
20 )
21
22 func TestFormatWithWrapUnbracedSite(t *testing.T) {
23 // eligible: wrapped
24 in := "localhost\nroot * /srv\nfile_server\n"
25 want := "localhost {\n\troot * /srv\n\tfile_server\n}\n"
26 if got := string(FormatWithOptions([]byte(in), FormatOptions{WrapUnbracedSite: true})); got != want {
27 t.Errorf("got %q, want %q", got, want)
28 }
29 // ineligible: unchanged from default formatting (no-op wrap)
30 snip := "(s) {\n\trespond 200\n}\n"
31 if got := string(FormatWithOptions([]byte(snip), FormatOptions{WrapUnbracedSite: true})); got != string(Format([]byte(snip))) {
32 t.Errorf("snippet should be a no-op for WrapUnbracedSite; got %q", got)
33 }
34 // default (option off) never wraps
35 if got := string(Format([]byte(in))); got != "localhost\nroot * /srv\nfile_server\n" {
36 t.Errorf("default Format must not wrap; got %q", got)
37 }
38 }
39
40 func TestWrapUnbracedSiteIdempotentAndSemantic(t *testing.T) {
41 in := "localhost\nrespond 200\n"
42 once := FormatWithOptions([]byte(in), FormatOptions{WrapUnbracedSite: true})
43 twice := FormatWithOptions(once, FormatOptions{WrapUnbracedSite: true})
44 if !bytes.Equal(once, twice) {
45 t.Errorf("not idempotent:\n once=%q\ntwice=%q", once, twice)
46 }
47 }
48
49 func TestWrapUnbracedSiteIdempotentReproducer(t *testing.T) {
50 // An input that used to be non-idempotent under WrapUnbracedSite: it reads
51 // as "not a single site" on the raw stream (a blank-line gap), but after
52 // formatTokens removes the blank line and folds a dangling brace, a second
53 // pass saw a single unbraced site and wrapped it. Deciding on the
54 // normalized stream makes the wrap decision stable. Parse rejects this
55 // input since the fix for unbalanced braces in site blocks (the stray "}"
56 // after a braceless site is an error), but the formatter works on the
57 // token stream and must stay idempotent on it regardless.
58 in := []byte(") 0((.b ))\na\t\tab(\n}\n\n { }")
59 if _, err := Parse("", in); err == nil {
60 t.Fatalf("reproducer should be rejected by Parse (unbalanced braces), got no error")
61 }
62 once := FormatWithOptions(in, FormatOptions{WrapUnbracedSite: true})
63 twice := FormatWithOptions(once, FormatOptions{WrapUnbracedSite: true})
64 if !bytes.Equal(once, twice) {
65 t.Errorf("not idempotent:\n once=%q\ntwice=%q", once, twice)
66 }
67 }
68
69 func FuzzWrapUnbracedSiteIdempotent(f *testing.F) {
70 seeds := []string{
71 "localhost\nrespond 200\n",
72 "localhost\nroot * /srv\nfile_server\n",
73 "example.com\nreverse_proxy {\n\tto a:80\n}\n",
74 "a.com\nrespond 200\n\nb.com\nrespond 404\n",
75 "(snip) {\n\trespond 200\n}\n",
76 ") 0((.b ))\na\t\tab(\n}\n\n { }",
77 "localhost {\n\trespond 200\n}\n",
78 }
79 for _, s := range seeds {
80 f.Add([]byte(s))
81 }
82 f.Fuzz(func(t *testing.T, in []byte) {
83 // Valid-only, like FuzzFormatIdempotent: skip inputs Parse rejects.
84 if _, err := Parse("", in); err != nil {
85 t.Skip()
86 }
87 once := FormatWithOptions(in, FormatOptions{WrapUnbracedSite: true})
88 twice := FormatWithOptions(once, FormatOptions{WrapUnbracedSite: true})
89 if !bytes.Equal(once, twice) {
90 t.Errorf("WrapUnbracedSite not idempotent for %q:\n once=%q\ntwice=%q", in, once, twice)
91 }
92 })
93 }
94
95 func TestIsSingleUnbracedSite(t *testing.T) {
96 yes := []string{
97 "localhost\nrespond 200\n",
98 "localhost\nreverse_proxy {\n\tto a:80\n}\n", // interior braces OK
99 }
100 no := []string{
101 "localhost {\n\trespond 200\n}\n", // already braced
102 "(snip) {\n\trespond 200\n}\n", // snippet
103 "&(route) {\n\trespond 200\n}\n", // named route
104 "{\n\tdebug\n}\n", // global options only
105 "a.com\nrespond 200\n\nb.com\nrespond 404\n", // multi-site (ambiguous)
106 "", // empty
107 }
108 for _, in := range yes {
109 toks, _ := Lex([]byte(in), "", LexOptions{Comments: true, Raw: true})
110 if !isSingleUnbracedSite(toks) {
111 t.Errorf("want single-unbraced-site for %q", in)
112 }
113 }
114 for _, in := range no {
115 toks, _ := Lex([]byte(in), "", LexOptions{Comments: true, Raw: true})
116 if isSingleUnbracedSite(toks) {
117 t.Errorf("did NOT expect single-unbraced-site for %q", in)
118 }
119 }
120 }