1 package awstesting
2
3 import (
4 "encoding/json"
5 "encoding/xml"
6 "fmt"
7 "net/url"
8 "reflect"
9 "regexp"
10 "sort"
11 "strings"
12 "testing"
13 )
14
15
16
17 func Match(t *testing.T, regex, expected string) {
18 t.Helper()
19
20 if !regexp.MustCompile(regex).Match([]byte(expected)) {
21 t.Errorf("%q\n\tdoes not match /%s/", expected, regex)
22 }
23 }
24
25
26 func AssertURL(t *testing.T, expect, actual string, msgAndArgs ...interface{}) bool {
27 t.Helper()
28
29 expectURL, err := url.Parse(expect)
30 if err != nil {
31 t.Errorf(errMsg("unable to parse expected URL", err, msgAndArgs))
32 return false
33 }
34 actualURL, err := url.Parse(actual)
35 if err != nil {
36 t.Errorf(errMsg("unable to parse actual URL", err, msgAndArgs))
37 return false
38 }
39
40 equal(t, expectURL.Host, actualURL.Host, msgAndArgs...)
41 equal(t, expectURL.Scheme, actualURL.Scheme, msgAndArgs...)
42 equal(t, expectURL.Path, actualURL.Path, msgAndArgs...)
43
44 return AssertQuery(t, expectURL.Query().Encode(), actualURL.Query().Encode(), msgAndArgs...)
45 }
46
47 var queryMapKey = regexp.MustCompile(`(.*?)\.[0-9]+\.key`)
48
49
50 func AssertQuery(t *testing.T, expect, actual string, msgAndArgs ...interface{}) bool {
51 t.Helper()
52
53 expectQ, err := url.ParseQuery(expect)
54 if err != nil {
55 t.Errorf(errMsg("unable to parse expected Query", err, msgAndArgs))
56 return false
57 }
58 actualQ, err := url.ParseQuery(actual)
59 if err != nil {
60 t.Errorf(errMsg("unable to parse actual Query", err, msgAndArgs))
61 return false
62 }
63
64
65 if !equal(t, queryValueKeys(expectQ), queryValueKeys(actualQ), msgAndArgs...) {
66 return false
67 }
68
69 keys := map[string][]string{}
70 for key, v := range expectQ {
71 if queryMapKey.Match([]byte(key)) {
72 submatch := queryMapKey.FindStringSubmatch(key)
73 keys[submatch[1]] = append(keys[submatch[1]], v...)
74 }
75 }
76
77 for k, v := range keys {
78
79 for key := range expectQ {
80 if strings.HasPrefix(key, k) {
81 delete(expectQ, key)
82 }
83 }
84
85 sort.Strings(v)
86 for i, value := range v {
87 expectQ[fmt.Sprintf("%s.%d.key", k, i+1)] = []string{value}
88 }
89 }
90
91 for k, expectQVals := range expectQ {
92 sort.Strings(expectQVals)
93 actualQVals := actualQ[k]
94 sort.Strings(actualQVals)
95 if !equal(t, expectQVals, actualQVals, msgAndArgs...) {
96 return false
97 }
98 }
99
100 return true
101 }
102
103
104 func AssertJSON(t *testing.T, expect, actual string, msgAndArgs ...interface{}) bool {
105 t.Helper()
106
107 expectVal := map[string]interface{}{}
108 if err := json.Unmarshal([]byte(expect), &expectVal); err != nil {
109 t.Errorf(errMsg("unable to parse expected JSON", err, msgAndArgs...))
110 return false
111 }
112
113 actualVal := map[string]interface{}{}
114 if err := json.Unmarshal([]byte(actual), &actualVal); err != nil {
115 t.Errorf(errMsg("unable to parse actual JSON", err, msgAndArgs...))
116 return false
117 }
118
119 return equal(t, expectVal, actualVal, msgAndArgs...)
120 }
121
122
123 func AssertXML(t *testing.T, expect, actual string, container interface{}, msgAndArgs ...interface{}) bool {
124 expectVal := container
125 if err := xml.Unmarshal([]byte(expect), &expectVal); err != nil {
126 t.Errorf(errMsg("unable to parse expected XML", err, msgAndArgs...))
127 }
128
129 actualVal := container
130 if err := xml.Unmarshal([]byte(actual), &actualVal); err != nil {
131 t.Errorf(errMsg("unable to parse actual XML", err, msgAndArgs...))
132 }
133 return equal(t, expectVal, actualVal, msgAndArgs...)
134 }
135
136
137 func DidPanic(fn func()) (bool, interface{}) {
138 var paniced bool
139 var msg interface{}
140 func() {
141 defer func() {
142 if msg = recover(); msg != nil {
143 paniced = true
144 }
145 }()
146 fn()
147 }()
148
149 return paniced, msg
150 }
151
152
153
154
155
156
157
158 func objectsAreEqual(expected, actual interface{}) bool {
159 if expected == nil || actual == nil {
160 return expected == actual
161 }
162
163 return reflect.DeepEqual(expected, actual)
164 }
165
166
167
168
169
170
171
172
173
174 func equal(t *testing.T, expected, actual interface{}, msgAndArgs ...interface{}) bool {
175 t.Helper()
176
177 if !objectsAreEqual(expected, actual) {
178 t.Errorf("%s\n%s", messageFromMsgAndArgs(msgAndArgs),
179 SprintExpectActual(expected, actual))
180 return false
181 }
182
183 return true
184 }
185
186 func errMsg(baseMsg string, err error, msgAndArgs ...interface{}) string {
187 message := messageFromMsgAndArgs(msgAndArgs)
188 if message != "" {
189 message += ", "
190 }
191 return fmt.Sprintf("%s%s, %v", message, baseMsg, err)
192 }
193
194
195
196 func messageFromMsgAndArgs(msgAndArgs []interface{}) string {
197 if len(msgAndArgs) == 0 || msgAndArgs == nil {
198 return ""
199 }
200 if len(msgAndArgs) == 1 {
201 return msgAndArgs[0].(string)
202 }
203 if len(msgAndArgs) > 1 {
204 return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
205 }
206 return ""
207 }
208
209 func queryValueKeys(v url.Values) []string {
210 keys := make([]string, 0, len(v))
211 for k := range v {
212 keys = append(keys, k)
213 }
214 sort.Strings(keys)
215 return keys
216 }
217
218
219
220 func SprintExpectActual(expect, actual interface{}) string {
221 return fmt.Sprintf("expect: %+v\nactual: %+v\n", expect, actual)
222 }
223
View as plain text