]> Cypherpunks.ru repositories - gostls13.git/blob - src/net/http/server_test.go
b0cc093d43dd3992ad68c6e2524a56b11435c7ad
[gostls13.git] / src / net / http / server_test.go
1 // Copyright 2018 The Go Authors. 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
5 // Server unit tests
6
7 package http
8
9 import (
10         "fmt"
11         "net/url"
12         "regexp"
13         "testing"
14         "time"
15 )
16
17 func TestServerTLSHandshakeTimeout(t *testing.T) {
18         tests := []struct {
19                 s    *Server
20                 want time.Duration
21         }{
22                 {
23                         s:    &Server{},
24                         want: 0,
25                 },
26                 {
27                         s: &Server{
28                                 ReadTimeout: -1,
29                         },
30                         want: 0,
31                 },
32                 {
33                         s: &Server{
34                                 ReadTimeout: 5 * time.Second,
35                         },
36                         want: 5 * time.Second,
37                 },
38                 {
39                         s: &Server{
40                                 ReadTimeout:  5 * time.Second,
41                                 WriteTimeout: -1,
42                         },
43                         want: 5 * time.Second,
44                 },
45                 {
46                         s: &Server{
47                                 ReadTimeout:  5 * time.Second,
48                                 WriteTimeout: 4 * time.Second,
49                         },
50                         want: 4 * time.Second,
51                 },
52                 {
53                         s: &Server{
54                                 ReadTimeout:       5 * time.Second,
55                                 ReadHeaderTimeout: 2 * time.Second,
56                                 WriteTimeout:      4 * time.Second,
57                         },
58                         want: 2 * time.Second,
59                 },
60         }
61         for i, tt := range tests {
62                 got := tt.s.tlsHandshakeTimeout()
63                 if got != tt.want {
64                         t.Errorf("%d. got %v; want %v", i, got, tt.want)
65                 }
66         }
67 }
68
69 type handler struct{ i int }
70
71 func (handler) ServeHTTP(ResponseWriter, *Request) {}
72
73 func TestFindHandler(t *testing.T) {
74         mux := NewServeMux()
75         for _, ph := range []struct {
76                 pat string
77                 h   Handler
78         }{
79                 {"/", &handler{1}},
80                 {"/foo/", &handler{2}},
81                 {"/foo", &handler{3}},
82                 {"/bar/", &handler{4}},
83                 {"//foo", &handler{5}},
84         } {
85                 mux.Handle(ph.pat, ph.h)
86         }
87
88         for _, test := range []struct {
89                 method      string
90                 path        string
91                 wantHandler string
92         }{
93                 {"GET", "/", "&http.handler{i:1}"},
94                 {"GET", "//", `&http.redirectHandler{url:"/", code:301}`},
95                 {"GET", "/foo/../bar/./..//baz", `&http.redirectHandler{url:"/baz", code:301}`},
96                 {"GET", "/foo", "&http.handler{i:3}"},
97                 {"GET", "/foo/x", "&http.handler{i:2}"},
98                 {"GET", "/bar/x", "&http.handler{i:4}"},
99                 {"GET", "/bar", `&http.redirectHandler{url:"/bar/", code:301}`},
100                 {"CONNECT", "/", "&http.handler{i:1}"},
101                 {"CONNECT", "//", "&http.handler{i:1}"},
102                 {"CONNECT", "//foo", "&http.handler{i:5}"},
103                 {"CONNECT", "/foo/../bar/./..//baz", "&http.handler{i:2}"},
104                 {"CONNECT", "/foo", "&http.handler{i:3}"},
105                 {"CONNECT", "/foo/x", "&http.handler{i:2}"},
106                 {"CONNECT", "/bar/x", "&http.handler{i:4}"},
107                 {"CONNECT", "/bar", `&http.redirectHandler{url:"/bar/", code:301}`},
108         } {
109                 var r Request
110                 r.Method = test.method
111                 r.Host = "example.com"
112                 r.URL = &url.URL{Path: test.path}
113                 gotH, _ := mux.findHandler(&r)
114                 got := fmt.Sprintf("%#v", gotH)
115                 if got != test.wantHandler {
116                         t.Errorf("%s %q: got %q, want %q", test.method, test.path, got, test.wantHandler)
117                 }
118         }
119 }
120
121 func TestRegisterErr(t *testing.T) {
122         mux := NewServeMux()
123         h := &handler{}
124         mux.Handle("/a", h)
125
126         for _, test := range []struct {
127                 pattern    string
128                 handler    Handler
129                 wantRegexp string
130         }{
131                 {"", h, "invalid pattern"},
132                 {"/", nil, "nil handler"},
133                 {"/", HandlerFunc(nil), "nil handler"},
134                 {"/{x", h, `parsing "/\{x": bad wildcard segment`},
135                 {"/a", h, `conflicts with pattern.* \(registered at .*/server_test.go:\d+`},
136         } {
137                 t.Run(fmt.Sprintf("%s:%#v", test.pattern, test.handler), func(t *testing.T) {
138                         err := mux.registerErr(test.pattern, test.handler)
139                         if err == nil {
140                                 t.Fatal("got nil error")
141                         }
142                         re := regexp.MustCompile(test.wantRegexp)
143                         if g := err.Error(); !re.MatchString(g) {
144                                 t.Errorf("\ngot %q\nwant string matching %q", g, test.wantRegexp)
145                         }
146                 })
147         }
148 }
149
150 func TestExactMatch(t *testing.T) {
151         for _, test := range []struct {
152                 pattern string
153                 path    string
154                 want    bool
155         }{
156                 {"", "/a", false},
157                 {"/", "/a", false},
158                 {"/a", "/a", true},
159                 {"/a/{x...}", "/a/b", false},
160                 {"/a/{x}", "/a/b", true},
161                 {"/a/b/", "/a/b/", true},
162                 {"/a/b/{$}", "/a/b/", true},
163                 {"/a/", "/a/b/", false},
164         } {
165                 var n *routingNode
166                 if test.pattern != "" {
167                         pat := mustParsePattern(t, test.pattern)
168                         n = &routingNode{pattern: pat}
169                 }
170                 got := exactMatch(n, test.path)
171                 if got != test.want {
172                         t.Errorf("%q, %s: got %t, want %t", test.pattern, test.path, got, test.want)
173                 }
174         }
175 }
176
177 func BenchmarkServerMatch(b *testing.B) {
178         fn := func(w ResponseWriter, r *Request) {
179                 fmt.Fprintf(w, "OK")
180         }
181         mux := NewServeMux()
182         mux.HandleFunc("/", fn)
183         mux.HandleFunc("/index", fn)
184         mux.HandleFunc("/home", fn)
185         mux.HandleFunc("/about", fn)
186         mux.HandleFunc("/contact", fn)
187         mux.HandleFunc("/robots.txt", fn)
188         mux.HandleFunc("/products/", fn)
189         mux.HandleFunc("/products/1", fn)
190         mux.HandleFunc("/products/2", fn)
191         mux.HandleFunc("/products/3", fn)
192         mux.HandleFunc("/products/3/image.jpg", fn)
193         mux.HandleFunc("/admin", fn)
194         mux.HandleFunc("/admin/products/", fn)
195         mux.HandleFunc("/admin/products/create", fn)
196         mux.HandleFunc("/admin/products/update", fn)
197         mux.HandleFunc("/admin/products/delete", fn)
198
199         paths := []string{"/", "/notfound", "/admin/", "/admin/foo", "/contact", "/products",
200                 "/products/", "/products/3/image.jpg"}
201         b.StartTimer()
202         for i := 0; i < b.N; i++ {
203                 r, err := NewRequest("GET", "http://example.com/"+paths[i%len(paths)], nil)
204                 if err != nil {
205                         b.Fatal(err)
206                 }
207                 if h, p := mux.findHandler(r); h != nil && p == "" {
208                         b.Error("impossible")
209                 }
210         }
211         b.StopTimer()
212 }