Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(248)

Side by Side Diff: server/router/router_test.go

Issue 2043423004: Make HTTP middleware easier to use (Closed) Base URL: https://github.com/luci/luci-go@master
Patch Set: gaemiddleware: add middleware func for WithProd Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « server/router/router.go ('k') | server/settings/admin/handlers.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package router
6
7 import (
8 "io"
9 "io/ioutil"
10 "net/http"
11 "net/http/httptest"
12 "strings"
13 "testing"
14
15 "golang.org/x/net/context"
16
17 . "github.com/smartystreets/goconvey/convey"
18 )
19
20 func TestRouter(t *testing.T) {
21 t.Parallel()
22
23 outputKey := "output"
24 client := &http.Client{}
25 appendValue := func(c context.Context, key string, val string) context.C ontext {
26 var current []string
27 if v := c.Value(key); v != nil {
28 current = v.([]string)
29 }
30 return context.WithValue(c, key, append(current, val))
31 }
32 a := func(c *Context, next Handler) {
33 c.Context = appendValue(c.Context, outputKey, "a:before")
34 next(c)
35 c.Context = appendValue(c.Context, outputKey, "a:after")
36 }
37 b := func(c *Context, next Handler) {
38 c.Context = appendValue(c.Context, outputKey, "b:before")
39 next(c)
40 c.Context = appendValue(c.Context, outputKey, "b:after")
41 }
42 c := func(c *Context, next Handler) {
43 c.Context = appendValue(c.Context, outputKey, "c")
44 next(c)
45 }
46 d := func(c *Context, next Handler) {
47 next(c)
48 c.Context = appendValue(c.Context, outputKey, "d")
49 }
50 stop := func(_ *Context, _ Handler) {}
51 handler := func(c *Context) {
52 c.Context = appendValue(c.Context, outputKey, "handler")
53 }
54
55 Convey("Router", t, func() {
56 r := New()
57
58 Convey("New", func() {
59 Convey("Should initialize non-nil httprouter.Router", fu nc() {
60 So(r.hrouter, ShouldNotBeNil)
61 })
62 })
63
64 Convey("Use", func() {
65 Convey("Should append middleware", func() {
66 So(len(r.middleware), ShouldEqual, 0)
67 r.Use(MiddlewareChain{a, b})
68 So(len(r.middleware), ShouldEqual, 2)
69 })
70 })
71
72 Convey("Subrouter", func() {
73 Convey("Should create new router with values from origin al router", func() {
74 r.BasePath = "/foo"
75 r.Use(MiddlewareChain{a, b})
76 r2 := r.Subrouter("bar")
77 So(r.hrouter, ShouldPointTo, r2.hrouter)
78 So(r2.BasePath, ShouldEqual, "/foo/bar")
79 So(&r.middleware[0], ShouldNotEqual, &r2.middlew are[0])
80 So(&r.middleware[1], ShouldNotEqual, &r2.middlew are[1])
81 So(len(r.middleware), ShouldEqual, len(r2.middle ware))
82 So(r.middleware[0], ShouldEqual, r2.middleware[0 ])
83 So(r.middleware[1], ShouldEqual, r2.middleware[1 ])
84 })
85 })
86
87 Convey("Handle", func() {
88 Convey("Should not modify existing empty r.middleware sl ice", func() {
89 So(len(r.middleware), ShouldEqual, 0)
90 r.Handle("GET", "/bar", MiddlewareChain{b, c}, h andler)
91 So(len(r.middleware), ShouldEqual, 0)
92 })
93
94 Convey("Should not modify existing r.middleware slice", func() {
95 r.Use(MiddlewareChain{a})
96 So(len(r.middleware), ShouldEqual, 1)
97 r.Handle("GET", "/bar", MiddlewareChain{b, c}, h andler)
98 So(len(r.middleware), ShouldEqual, 1)
99 })
100 })
101
102 Convey("run", func() {
103 ctx := &Context{Context: context.Background()}
104
105 Convey("Should execute handler when using nil middleware s", func() {
106 run(ctx, nil, nil, handler)
107 So(ctx.Context.Value(outputKey), ShouldResemble, []string{"handler"})
108 })
109
110 Convey("Should execute middlewares and handler in order" , func() {
111 m := MiddlewareChain{a, b, c}
112 n := MiddlewareChain{d}
113 run(ctx, m, n, handler)
114 So(ctx.Context.Value(outputKey), ShouldResemble,
115 []string{"a:before", "b:before", "c", "h andler", "d", "b:after", "a:after"},
116 )
117 })
118
119 Convey("Should not execute upcoming middleware/handlers if next is not called", func() {
120 mc := MiddlewareChain{a, stop, b}
121 run(ctx, mc, nil, handler)
122 So(ctx.Context.Value(outputKey), ShouldResemble, []string{"a:before", "a:after"})
123 })
124
125 Convey("Should execute next middleware when it encounter s nil middleware", func() {
126 Convey("At start of first chain", func() {
127 run(ctx, MiddlewareChain{nil, a}, Middle wareChain{b}, handler)
128 So(ctx.Context.Value(outputKey), ShouldR esemble, []string{"a:before", "b:before", "handler", "b:after", "a:after"})
129 })
130 Convey("At start of second chain", func() {
131 run(ctx, MiddlewareChain{a}, MiddlewareC hain{nil, b}, handler)
132 So(ctx.Context.Value(outputKey), ShouldR esemble, []string{"a:before", "b:before", "handler", "b:after", "a:after"})
133 })
134 Convey("At end of first chain", func() {
135 run(ctx, MiddlewareChain{a, nil}, Middle wareChain{b}, handler)
136 So(ctx.Context.Value(outputKey), ShouldR esemble, []string{"a:before", "b:before", "handler", "b:after", "a:after"})
137 })
138 Convey("At end of second chain", func() {
139 run(ctx, MiddlewareChain{a}, MiddlewareC hain{b, nil}, handler)
140 So(ctx.Context.Value(outputKey), ShouldR esemble, []string{"a:before", "b:before", "handler", "b:after", "a:after"})
141 })
142 })
143 })
144
145 Convey("ServeHTTP", func() {
146 ts := httptest.NewServer(r)
147 a := func(c *Context, next Handler) {
148 c.Context = appendValue(c.Context, outputKey, "a :before")
149 next(c)
150 c.Context = appendValue(c.Context, outputKey, "a :after")
151 io.WriteString(c.Writer, strings.Join(c.Context. Value(outputKey).([]string), ","))
152 }
153
154 Convey("Should execute middleware registered in Use and Handle in order", func() {
155 r.Use(MiddlewareChain{a})
156 r.GET("/ab", MiddlewareChain{b}, handler)
157 res, err := client.Get(ts.URL + "/ab")
158 So(err, ShouldBeNil)
159 defer res.Body.Close()
160 So(res.StatusCode, ShouldEqual, http.StatusOK)
161 p, err := ioutil.ReadAll(res.Body)
162 So(err, ShouldBeNil)
163 So(string(p), ShouldEqual, strings.Join(
164 []string{"a:before", "b:before", "handle r", "b:after", "a:after"},
165 ",",
166 ))
167 })
168
169 Convey("Should return method not allowed for existing pa th but wrong method in request", func() {
170 r.POST("/comment", nil, handler)
171 res, err := client.Get(ts.URL + "/comment")
172 So(err, ShouldBeNil)
173 defer res.Body.Close()
174 So(res.StatusCode, ShouldEqual, http.StatusMetho dNotAllowed)
175 })
176
177 Convey("Should return expected response from handler", f unc() {
178 handler := func(c *Context) {
179 c.Writer.Write([]byte("Hello, " + c.Para ms[0].Value))
180 }
181 r.GET("/hello/:name", MiddlewareChain{c, d}, han dler)
182 res, err := client.Get(ts.URL + "/hello/世界")
183 So(err, ShouldBeNil)
184 defer res.Body.Close()
185 So(res.StatusCode, ShouldEqual, http.StatusOK)
186 p, err := ioutil.ReadAll(res.Body)
187 So(err, ShouldBeNil)
188 So(string(p), ShouldEqual, "Hello, 世界")
189 })
190
191 Reset(func() {
192 ts.Close()
193 })
194 })
195
196 Convey("makeBasePath", func() {
197 cases := []struct{ base, relative, result string }{
198 {"/", "", "/"},
199 {"", "", "/"},
200 {"foo", "", "/foo"},
201 {"foo/", "", "/foo/"},
202 {"foo", "/", "/foo/"},
203 {"foo", "bar", "/foo/bar"},
204 {"foo/", "bar", "/foo/bar"},
205 {"foo", "bar/", "/foo/bar/"},
206 {"/foo", "/bar", "/foo/bar"},
207 {"/foo/", "/bar", "/foo/bar"},
208 {"foo//", "///bar", "/foo/bar"},
209 {"foo", "bar///baz/qux", "/foo/bar/baz/qux"},
210 {"//foo//", "///bar///baz/qux/", "/foo/bar/baz/q ux/"},
211 }
212 for _, c := range cases {
213 So(makeBasePath(c.base, c.relative), ShouldEqual , c.result)
214 }
215 })
216 })
217 }
OLDNEW
« no previous file with comments | « server/router/router.go ('k') | server/settings/admin/handlers.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698