13 changed files with 370 additions and 174 deletions
@ -1,87 +1,70 @@
@@ -1,87 +1,70 @@
|
||||
version: 2.0 |
||||
version: 2.1 |
||||
|
||||
jobs: |
||||
# Base test configuration for Go library tests Each distinct version should |
||||
# inherit this base, and override (at least) the container image used. |
||||
"test": &test |
||||
"test": |
||||
parameters: |
||||
version: |
||||
type: string |
||||
default: "latest" |
||||
golint: |
||||
type: boolean |
||||
default: true |
||||
modules: |
||||
type: boolean |
||||
default: true |
||||
goproxy: |
||||
type: string |
||||
default: "" |
||||
docker: |
||||
- image: circleci/golang:latest |
||||
- image: "circleci/golang:<< parameters.version >>" |
||||
working_directory: /go/src/github.com/gorilla/mux |
||||
steps: &steps |
||||
# Our build steps: we checkout the repo, fetch our deps, lint, and finally |
||||
# run "go test" on the package. |
||||
environment: |
||||
GO111MODULE: "on" |
||||
GOPROXY: "<< parameters.goproxy >>" |
||||
steps: |
||||
- checkout |
||||
# Logs the version in our build logs, for posterity |
||||
- run: go version |
||||
- run: |
||||
name: "Print the Go version" |
||||
command: > |
||||
go version |
||||
- run: |
||||
name: "Fetch dependencies" |
||||
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 |
||||
- run: |
||||
name: "Run golint" |
||||
command: > |
||||
if [ "${LATEST}" = true ] && [ -z "${SKIP_GOLINT}" ]; then |
||||
if [ << parameters.version >> = "latest" ] && [ << parameters.golint >> = true ]; then |
||||
go get -u golang.org/x/lint/golint |
||||
golint ./... |
||||
fi |
||||
- run: |
||||
name: "Run gofmt" |
||||
command: > |
||||
if [[ "${LATEST}" = true ]]; then |
||||
if [[ << parameters.version >> = "latest" ]]; then |
||||
diff -u <(echo -n) <(gofmt -d -e .) |
||||
fi |
||||
- run: |
||||
name: "Run go vet" |
||||
command: > |
||||
if [[ "${LATEST}" = true ]]; then |
||||
command: > |
||||
if [[ << parameters.version >> = "latest" ]]; then |
||||
go vet -v ./... |
||||
fi |
||||
- run: go test -v -race ./... |
||||
|
||||
"latest": |
||||
<<: *test |
||||
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 |
||||
- run: |
||||
name: "Run go test (+ race detector)" |
||||
command: > |
||||
go test -v -race ./... |
||||
|
||||
workflows: |
||||
version: 2 |
||||
build: |
||||
tests: |
||||
jobs: |
||||
- "latest" |
||||
- "1.12" |
||||
- "1.11" |
||||
- "1.10" |
||||
- "1.9" |
||||
- "1.8" |
||||
- "1.7" |
||||
- test: |
||||
matrix: |
||||
parameters: |
||||
version: ["latest", "1.15", "1.14", "1.13", "1.12", "1.11"] |
||||
|
||||
@ -1,18 +0,0 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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