This repository has been archived by the owner on Jun 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsimplechecker.go
123 lines (114 loc) · 3.73 KB
/
simplechecker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package gandalf
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"github.com/JumboInteractiveLimited/Gandalf/check"
)
// SimpleChecker implements a Checker that asserts the expected HTTP status
// code, headers, and uses pathing.check.Func for checking the contents of the
// body.
type SimpleChecker struct {
// HTTP Status code expected, ignored if left as default (0).
HTTPStatus int
// Assert that these headers have at least the values given. ignored if left as default.
Headers http.Header
// Uses a check.Func to assert the body is as expected.
BodyCheck check.Func
// Provide an example response body that should meet BodyCheck.
ExampleBody string
}
// GetResponse returns a new HTTP response that should meet all checks.
func (c *SimpleChecker) GetResponse() *http.Response {
r := SaneResponse()
r.StatusCode = c.HTTPStatus
r.Status = fmt.Sprintf("%d %s", c.HTTPStatus, http.StatusText(c.HTTPStatus))
r.Header = c.Headers
r.Body = ioutil.NopCloser(bytes.NewBufferString(c.ExampleBody))
r.ContentLength = int64(len(c.ExampleBody))
return r
}
// Assert the given HTTP response has the expected status code
func (c *SimpleChecker) assertStatus(res *http.Response) (err error) {
if c.HTTPStatus != 0 && res.StatusCode != c.HTTPStatus {
err = fmt.Errorf("HTTP Status code %d (%s) does not match expected %d (%s)",
res.StatusCode, http.StatusText(res.StatusCode), c.HTTPStatus, http.StatusText(c.HTTPStatus))
}
return err
}
func splitHeaders(in http.Header) (out http.Header) {
if len(in) > 0 {
out = http.Header{}
}
for k, v := range in {
for _, hv := range v {
if strings.Contains(hv, ",") {
for _, pv := range strings.Split(hv, ",") {
out.Add(k, strings.TrimSpace(pv))
}
} else {
out.Add(k, hv)
}
}
}
return out
}
// Assert the given HTTP response has the expected headers, this check allows
// for additional headers to those that are expected without error but all expected
// headers must have (at least) the specified value(s).
func (c *SimpleChecker) assertHeaders(responseHeaders http.Header) (err error) {
if len(c.Headers) == 0 {
return nil
}
for expectedKey := range c.Headers {
hasHeaderKey := false
for k := range responseHeaders {
if k == expectedKey {
hasHeaderKey = true
}
}
if !hasHeaderKey {
return fmt.Errorf("Expected header key %#v not found in response", expectedKey)
}
for _, cv := range c.Headers[expectedKey] {
hasHeaderValue := false
for _, rv := range responseHeaders[expectedKey] {
if rv == cv {
hasHeaderValue = true
}
}
if !hasHeaderValue {
return fmt.Errorf("Expected header value %#v not found in header key %#v with %d values %v",
cv, expectedKey, len(responseHeaders[expectedKey]), responseHeaders[expectedKey])
}
}
}
return err
}
// Check that the on the given responses body is as expected. The
// BodyCheck field on SimpleChecker can be either a single check.Func
// or you could use pathing.Checks to extract data from a structured
// text body. If BodyCheck is not set then it will use a string
// equality against the ExampleBody field.
func (c *SimpleChecker) assertBody(res *http.Response) (err error) {
if c.BodyCheck == nil {
c.BodyCheck = check.Equality(c.ExampleBody)
}
return c.BodyCheck(GetResponseBody(res))
}
// Assert the given HTTP response meets all checks.
// Executes methods in the following order:
// 1) SimpleChecker.assertStatus
// 2) SimpleChecker.assertHeaders
// 3) SimpleChecker.assertBody
func (c *SimpleChecker) Assert(res *http.Response) error {
if e := c.assertStatus(res); e != nil {
return fmt.Errorf("Status check failed, response body was:\n%s\n%s", GetResponseBody(res), e)
}
if e := c.assertHeaders(splitHeaders(res.Header)); e != nil {
return e
}
return c.assertBody(res)
}