assert.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package awstesting
  2. import (
  3. "encoding/json"
  4. "encoding/xml"
  5. "fmt"
  6. "net/url"
  7. "reflect"
  8. "regexp"
  9. "sort"
  10. "strings"
  11. "testing"
  12. )
  13. // Match is a testing helper to test for testing error by comparing expected
  14. // with a regular expression.
  15. func Match(t *testing.T, regex, expected string) {
  16. if !regexp.MustCompile(regex).Match([]byte(expected)) {
  17. t.Errorf("%q\n\tdoes not match /%s/", expected, regex)
  18. }
  19. }
  20. // AssertURL verifies the expected URL is matches the actual.
  21. func AssertURL(t *testing.T, expect, actual string, msgAndArgs ...interface{}) bool {
  22. expectURL, err := url.Parse(expect)
  23. if err != nil {
  24. t.Errorf(errMsg("unable to parse expected URL", err, msgAndArgs))
  25. return false
  26. }
  27. actualURL, err := url.Parse(actual)
  28. if err != nil {
  29. t.Errorf(errMsg("unable to parse actual URL", err, msgAndArgs))
  30. return false
  31. }
  32. equal(t, expectURL.Host, actualURL.Host, msgAndArgs...)
  33. equal(t, expectURL.Scheme, actualURL.Scheme, msgAndArgs...)
  34. equal(t, expectURL.Path, actualURL.Path, msgAndArgs...)
  35. return AssertQuery(t, expectURL.Query().Encode(), actualURL.Query().Encode(), msgAndArgs...)
  36. }
  37. var queryMapKey = regexp.MustCompile("(.*?)\\.[0-9]+\\.key")
  38. // AssertQuery verifies the expect HTTP query string matches the actual.
  39. func AssertQuery(t *testing.T, expect, actual string, msgAndArgs ...interface{}) bool {
  40. expectQ, err := url.ParseQuery(expect)
  41. if err != nil {
  42. t.Errorf(errMsg("unable to parse expected Query", err, msgAndArgs))
  43. return false
  44. }
  45. actualQ, err := url.ParseQuery(actual)
  46. if err != nil {
  47. t.Errorf(errMsg("unable to parse actual Query", err, msgAndArgs))
  48. return false
  49. }
  50. // Make sure the keys are the same
  51. if !equal(t, queryValueKeys(expectQ), queryValueKeys(actualQ), msgAndArgs...) {
  52. return false
  53. }
  54. keys := map[string][]string{}
  55. for key, v := range expectQ {
  56. if queryMapKey.Match([]byte(key)) {
  57. submatch := queryMapKey.FindStringSubmatch(key)
  58. keys[submatch[1]] = append(keys[submatch[1]], v...)
  59. }
  60. }
  61. for k, v := range keys {
  62. // clear all keys that have prefix
  63. for key := range expectQ {
  64. if strings.HasPrefix(key, k) {
  65. delete(expectQ, key)
  66. }
  67. }
  68. sort.Strings(v)
  69. for i, value := range v {
  70. expectQ[fmt.Sprintf("%s.%d.key", k, i+1)] = []string{value}
  71. }
  72. }
  73. for k, expectQVals := range expectQ {
  74. sort.Strings(expectQVals)
  75. actualQVals := actualQ[k]
  76. sort.Strings(actualQVals)
  77. if !equal(t, expectQVals, actualQVals, msgAndArgs...) {
  78. return false
  79. }
  80. }
  81. return true
  82. }
  83. // AssertJSON verifies that the expect json string matches the actual.
  84. func AssertJSON(t *testing.T, expect, actual string, msgAndArgs ...interface{}) bool {
  85. expectVal := map[string]interface{}{}
  86. if err := json.Unmarshal([]byte(expect), &expectVal); err != nil {
  87. t.Errorf(errMsg("unable to parse expected JSON", err, msgAndArgs...))
  88. return false
  89. }
  90. actualVal := map[string]interface{}{}
  91. if err := json.Unmarshal([]byte(actual), &actualVal); err != nil {
  92. t.Errorf(errMsg("unable to parse actual JSON", err, msgAndArgs...))
  93. return false
  94. }
  95. return equal(t, expectVal, actualVal, msgAndArgs...)
  96. }
  97. // AssertXML verifies that the expect xml string matches the actual.
  98. func AssertXML(t *testing.T, expect, actual string, container interface{}, msgAndArgs ...interface{}) bool {
  99. expectVal := container
  100. if err := xml.Unmarshal([]byte(expect), &expectVal); err != nil {
  101. t.Errorf(errMsg("unable to parse expected XML", err, msgAndArgs...))
  102. }
  103. actualVal := container
  104. if err := xml.Unmarshal([]byte(actual), &actualVal); err != nil {
  105. t.Errorf(errMsg("unable to parse actual XML", err, msgAndArgs...))
  106. }
  107. return equal(t, expectVal, actualVal, msgAndArgs...)
  108. }
  109. // DidPanic returns if the function paniced and returns true if the function paniced.
  110. func DidPanic(fn func()) (bool, interface{}) {
  111. var paniced bool
  112. var msg interface{}
  113. func() {
  114. defer func() {
  115. if msg = recover(); msg != nil {
  116. paniced = true
  117. }
  118. }()
  119. fn()
  120. }()
  121. return paniced, msg
  122. }
  123. // objectsAreEqual determines if two objects are considered equal.
  124. //
  125. // This function does no assertion of any kind.
  126. //
  127. // Based on github.com/stretchr/testify/assert.ObjectsAreEqual
  128. // Copied locally to prevent non-test build dependencies on testify
  129. func objectsAreEqual(expected, actual interface{}) bool {
  130. if expected == nil || actual == nil {
  131. return expected == actual
  132. }
  133. return reflect.DeepEqual(expected, actual)
  134. }
  135. // Equal asserts that two objects are equal.
  136. //
  137. // assert.Equal(t, 123, 123, "123 and 123 should be equal")
  138. //
  139. // Returns whether the assertion was successful (true) or not (false).
  140. //
  141. // Based on github.com/stretchr/testify/assert.Equal
  142. // Copied locally to prevent non-test build dependencies on testify
  143. func equal(t *testing.T, expected, actual interface{}, msgAndArgs ...interface{}) bool {
  144. if !objectsAreEqual(expected, actual) {
  145. t.Errorf("%s\n%s", messageFromMsgAndArgs(msgAndArgs),
  146. SprintExpectActual(expected, actual))
  147. return false
  148. }
  149. return true
  150. }
  151. func errMsg(baseMsg string, err error, msgAndArgs ...interface{}) string {
  152. message := messageFromMsgAndArgs(msgAndArgs)
  153. if message != "" {
  154. message += ", "
  155. }
  156. return fmt.Sprintf("%s%s, %v", message, baseMsg, err)
  157. }
  158. // Based on github.com/stretchr/testify/assert.messageFromMsgAndArgs
  159. // Copied locally to prevent non-test build dependencies on testify
  160. func messageFromMsgAndArgs(msgAndArgs []interface{}) string {
  161. if len(msgAndArgs) == 0 || msgAndArgs == nil {
  162. return ""
  163. }
  164. if len(msgAndArgs) == 1 {
  165. return msgAndArgs[0].(string)
  166. }
  167. if len(msgAndArgs) > 1 {
  168. return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
  169. }
  170. return ""
  171. }
  172. func queryValueKeys(v url.Values) []string {
  173. keys := make([]string, 0, len(v))
  174. for k := range v {
  175. keys = append(keys, k)
  176. }
  177. sort.Strings(keys)
  178. return keys
  179. }
  180. // SprintExpectActual returns a string for test failure cases when the actual
  181. // value is not the same as the expected.
  182. func SprintExpectActual(expect, actual interface{}) string {
  183. return fmt.Sprintf("expect: %+v\nactual: %+v\n", expect, actual)
  184. }