13 changed files with 370 additions and 174 deletions
@ -1,87 +1,70 @@ |
|||||||
version: 2.0 |
version: 2.1 |
||||||
|
|
||||||
jobs: |
jobs: |
||||||
# Base test configuration for Go library tests Each distinct version should |
"test": |
||||||
# inherit this base, and override (at least) the container image used. |
parameters: |
||||||
"test": &test |
version: |
||||||
|
type: string |
||||||
|
default: "latest" |
||||||
|
golint: |
||||||
|
type: boolean |
||||||
|
default: true |
||||||
|
modules: |
||||||
|
type: boolean |
||||||
|
default: true |
||||||
|
goproxy: |
||||||
|
type: string |
||||||
|
default: "" |
||||||
docker: |
docker: |
||||||
- image: circleci/golang:latest |
- image: "circleci/golang:<< parameters.version >>" |
||||||
working_directory: /go/src/github.com/gorilla/mux |
working_directory: /go/src/github.com/gorilla/mux |
||||||
steps: &steps |
environment: |
||||||
# Our build steps: we checkout the repo, fetch our deps, lint, and finally |
GO111MODULE: "on" |
||||||
# run "go test" on the package. |
GOPROXY: "<< parameters.goproxy >>" |
||||||
|
steps: |
||||||
- checkout |
- checkout |
||||||
# Logs the version in our build logs, for posterity |
- run: |
||||||
- run: go version |
name: "Print the Go version" |
||||||
|
command: > |
||||||
|
go version |
||||||
- run: |
- run: |
||||||
name: "Fetch dependencies" |
name: "Fetch dependencies" |
||||||
command: > |
command: > |
||||||
go get -t -v ./... |
if [[ << parameters.modules >> = true ]]; then |
||||||
|
go mod download |
||||||
|
export GO111MODULE=on |
||||||
|
else |
||||||
|
go get -v ./... |
||||||
|
fi |
||||||
# Only run gofmt, vet & lint against the latest Go version |
# Only run gofmt, vet & lint against the latest Go version |
||||||
- run: |
- run: |
||||||
name: "Run golint" |
name: "Run golint" |
||||||
command: > |
command: > |
||||||
if [ "${LATEST}" = true ] && [ -z "${SKIP_GOLINT}" ]; then |
if [ << parameters.version >> = "latest" ] && [ << parameters.golint >> = true ]; then |
||||||
go get -u golang.org/x/lint/golint |
go get -u golang.org/x/lint/golint |
||||||
golint ./... |
golint ./... |
||||||
fi |
fi |
||||||
- run: |
- run: |
||||||
name: "Run gofmt" |
name: "Run gofmt" |
||||||
command: > |
command: > |
||||||
if [[ "${LATEST}" = true ]]; then |
if [[ << parameters.version >> = "latest" ]]; then |
||||||
diff -u <(echo -n) <(gofmt -d -e .) |
diff -u <(echo -n) <(gofmt -d -e .) |
||||||
fi |
fi |
||||||
- run: |
- run: |
||||||
name: "Run go vet" |
name: "Run go vet" |
||||||
command: > |
command: > |
||||||
if [[ "${LATEST}" = true ]]; then |
if [[ << parameters.version >> = "latest" ]]; then |
||||||
go vet -v ./... |
go vet -v ./... |
||||||
fi |
fi |
||||||
- run: go test -v -race ./... |
- run: |
||||||
|
name: "Run go test (+ race detector)" |
||||||
"latest": |
command: > |
||||||
<<: *test |
go test -v -race ./... |
||||||
environment: |
|
||||||
LATEST: true |
|
||||||
|
|
||||||
"1.12": |
|
||||||
<<: *test |
|
||||||
docker: |
|
||||||
- image: circleci/golang:1.12 |
|
||||||
|
|
||||||
"1.11": |
|
||||||
<<: *test |
|
||||||
docker: |
|
||||||
- image: circleci/golang:1.11 |
|
||||||
|
|
||||||
"1.10": |
|
||||||
<<: *test |
|
||||||
docker: |
|
||||||
- image: circleci/golang:1.10 |
|
||||||
|
|
||||||
"1.9": |
|
||||||
<<: *test |
|
||||||
docker: |
|
||||||
- image: circleci/golang:1.9 |
|
||||||
|
|
||||||
"1.8": |
|
||||||
<<: *test |
|
||||||
docker: |
|
||||||
- image: circleci/golang:1.8 |
|
||||||
|
|
||||||
"1.7": |
|
||||||
<<: *test |
|
||||||
docker: |
|
||||||
- image: circleci/golang:1.7 |
|
||||||
|
|
||||||
workflows: |
workflows: |
||||||
version: 2 |
tests: |
||||||
build: |
|
||||||
jobs: |
jobs: |
||||||
- "latest" |
- test: |
||||||
- "1.12" |
matrix: |
||||||
- "1.11" |
parameters: |
||||||
- "1.10" |
version: ["latest", "1.15", "1.14", "1.13", "1.12", "1.11"] |
||||||
- "1.9" |
|
||||||
- "1.8" |
|
||||||
- "1.7" |
|
||||||
|
|||||||
@ -1,18 +0,0 @@ |
|||||||
package mux |
|
||||||
|
|
||||||
import ( |
|
||||||
"context" |
|
||||||
"net/http" |
|
||||||
) |
|
||||||
|
|
||||||
func contextGet(r *http.Request, key interface{}) interface{} { |
|
||||||
return r.Context().Value(key) |
|
||||||
} |
|
||||||
|
|
||||||
func contextSet(r *http.Request, key, val interface{}) *http.Request { |
|
||||||
if val == nil { |
|
||||||
return r |
|
||||||
} |
|
||||||
|
|
||||||
return r.WithContext(context.WithValue(r.Context(), key, val)) |
|
||||||
} |
|
||||||
@ -1,30 +0,0 @@ |
|||||||
package mux |
|
||||||
|
|
||||||
import ( |
|
||||||
"context" |
|
||||||
"net/http" |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
) |
|
||||||
|
|
||||||
func TestNativeContextMiddleware(t *testing.T) { |
|
||||||
withTimeout := func(h http.Handler) http.Handler { |
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
||||||
ctx, cancel := context.WithTimeout(r.Context(), time.Minute) |
|
||||||
defer cancel() |
|
||||||
h.ServeHTTP(w, r.WithContext(ctx)) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
r := NewRouter() |
|
||||||
r.Handle("/path/{foo}", withTimeout(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
||||||
vars := Vars(r) |
|
||||||
if vars["foo"] != "bar" { |
|
||||||
t.Fatal("Expected foo var to be set") |
|
||||||
} |
|
||||||
}))) |
|
||||||
|
|
||||||
rec := NewRecorder() |
|
||||||
req := newRequest("GET", "/path/bar") |
|
||||||
r.ServeHTTP(rec, req) |
|
||||||
} |
|
||||||
@ -0,0 +1,49 @@ |
|||||||
|
// +build go1.9
|
||||||
|
|
||||||
|
package mux |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"io/ioutil" |
||||||
|
"net/http" |
||||||
|
"net/http/httptest" |
||||||
|
"testing" |
||||||
|
) |
||||||
|
|
||||||
|
func TestSchemeMatchers(t *testing.T) { |
||||||
|
router := NewRouter() |
||||||
|
router.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { |
||||||
|
rw.Write([]byte("hello http world")) |
||||||
|
}).Schemes("http") |
||||||
|
router.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { |
||||||
|
rw.Write([]byte("hello https world")) |
||||||
|
}).Schemes("https") |
||||||
|
|
||||||
|
assertResponseBody := func(t *testing.T, s *httptest.Server, expectedBody string) { |
||||||
|
resp, err := s.Client().Get(s.URL) |
||||||
|
if err != nil { |
||||||
|
t.Fatalf("unexpected error getting from server: %v", err) |
||||||
|
} |
||||||
|
if resp.StatusCode != 200 { |
||||||
|
t.Fatalf("expected a status code of 200, got %v", resp.StatusCode) |
||||||
|
} |
||||||
|
body, err := ioutil.ReadAll(resp.Body) |
||||||
|
if err != nil { |
||||||
|
t.Fatalf("unexpected error reading body: %v", err) |
||||||
|
} |
||||||
|
if !bytes.Equal(body, []byte(expectedBody)) { |
||||||
|
t.Fatalf("response should be hello world, was: %q", string(body)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
t.Run("httpServer", func(t *testing.T) { |
||||||
|
s := httptest.NewServer(router) |
||||||
|
defer s.Close() |
||||||
|
assertResponseBody(t, s, "hello http world") |
||||||
|
}) |
||||||
|
t.Run("httpsServer", func(t *testing.T) { |
||||||
|
s := httptest.NewTLSServer(router) |
||||||
|
defer s.Close() |
||||||
|
assertResponseBody(t, s, "hello https world") |
||||||
|
}) |
||||||
|
} |
||||||
@ -0,0 +1,91 @@ |
|||||||
|
package mux |
||||||
|
|
||||||
|
import ( |
||||||
|
"net/url" |
||||||
|
"reflect" |
||||||
|
"strconv" |
||||||
|
"testing" |
||||||
|
) |
||||||
|
|
||||||
|
func Test_findFirstQueryKey(t *testing.T) { |
||||||
|
tests := []string{ |
||||||
|
"a=1&b=2", |
||||||
|
"a=1&a=2&a=banana", |
||||||
|
"ascii=%3Ckey%3A+0x90%3E", |
||||||
|
"a=1;b=2", |
||||||
|
"a=1&a=2;a=banana", |
||||||
|
"a==", |
||||||
|
"a=%2", |
||||||
|
"a=20&%20%3F&=%23+%25%21%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09:%2F@$%27%28%29%2A%2C%3B&a=30", |
||||||
|
"a=1& ?&=#+%!<>#\"{}|\\^[]`☺\t:/@$'()*,;&a=5", |
||||||
|
"a=xxxxxxxxxxxxxxxx&b=YYYYYYYYYYYYYYY&c=ppppppppppppppppppp&f=ttttttttttttttttt&a=uuuuuuuuuuuuu", |
||||||
|
} |
||||||
|
for _, query := range tests { |
||||||
|
t.Run(query, func(t *testing.T) { |
||||||
|
// Check against url.ParseQuery, ignoring the error.
|
||||||
|
all, _ := url.ParseQuery(query) |
||||||
|
for key, want := range all { |
||||||
|
t.Run(key, func(t *testing.T) { |
||||||
|
got, ok := findFirstQueryKey(query, key) |
||||||
|
if !ok { |
||||||
|
t.Error("Did not get expected key", key) |
||||||
|
} |
||||||
|
if !reflect.DeepEqual(got, want[0]) { |
||||||
|
t.Errorf("findFirstQueryKey(%s,%s) = %v, want %v", query, key, got, want[0]) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func Benchmark_findQueryKey(b *testing.B) { |
||||||
|
tests := []string{ |
||||||
|
"a=1&b=2", |
||||||
|
"ascii=%3Ckey%3A+0x90%3E", |
||||||
|
"a=20&%20%3F&=%23+%25%21%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09:%2F@$%27%28%29%2A%2C%3B&a=30", |
||||||
|
"a=xxxxxxxxxxxxxxxx&bbb=YYYYYYYYYYYYYYY&cccc=ppppppppppppppppppp&ddddd=ttttttttttttttttt&a=uuuuuuuuuuuuu", |
||||||
|
"a=;b=;c=;d=;e=;f=;g=;h=;i=,j=;k=", |
||||||
|
} |
||||||
|
for i, query := range tests { |
||||||
|
b.Run(strconv.Itoa(i), func(b *testing.B) { |
||||||
|
// Check against url.ParseQuery, ignoring the error.
|
||||||
|
all, _ := url.ParseQuery(query) |
||||||
|
b.ReportAllocs() |
||||||
|
b.ResetTimer() |
||||||
|
for i := 0; i < b.N; i++ { |
||||||
|
for key, _ := range all { |
||||||
|
_, _ = findFirstQueryKey(query, key) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func Benchmark_findQueryKeyGoLib(b *testing.B) { |
||||||
|
tests := []string{ |
||||||
|
"a=1&b=2", |
||||||
|
"ascii=%3Ckey%3A+0x90%3E", |
||||||
|
"a=20&%20%3F&=%23+%25%21%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09:%2F@$%27%28%29%2A%2C%3B&a=30", |
||||||
|
"a=xxxxxxxxxxxxxxxx&bbb=YYYYYYYYYYYYYYY&cccc=ppppppppppppppppppp&ddddd=ttttttttttttttttt&a=uuuuuuuuuuuuu", |
||||||
|
"a=;b=;c=;d=;e=;f=;g=;h=;i=,j=;k=", |
||||||
|
} |
||||||
|
for i, query := range tests { |
||||||
|
b.Run(strconv.Itoa(i), func(b *testing.B) { |
||||||
|
// Check against url.ParseQuery, ignoring the error.
|
||||||
|
all, _ := url.ParseQuery(query) |
||||||
|
var u url.URL |
||||||
|
u.RawQuery = query |
||||||
|
b.ReportAllocs() |
||||||
|
b.ResetTimer() |
||||||
|
for i := 0; i < b.N; i++ { |
||||||
|
for key, _ := range all { |
||||||
|
v := u.Query()[key] |
||||||
|
if len(v) > 0 { |
||||||
|
_ = v[0] |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue