You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.6 KiB

  1. package assertion
  2. import (
  3. "fmt"
  4. "reflect"
  5. "github.com/onsi/gomega/types"
  6. )
  7. type Assertion struct {
  8. actualInput interface{}
  9. failWrapper *types.GomegaFailWrapper
  10. offset int
  11. extra []interface{}
  12. }
  13. func New(actualInput interface{}, failWrapper *types.GomegaFailWrapper, offset int, extra ...interface{}) *Assertion {
  14. return &Assertion{
  15. actualInput: actualInput,
  16. failWrapper: failWrapper,
  17. offset: offset,
  18. extra: extra,
  19. }
  20. }
  21. func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
  22. assertion.failWrapper.TWithHelper.Helper()
  23. return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
  24. }
  25. func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
  26. assertion.failWrapper.TWithHelper.Helper()
  27. return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
  28. }
  29. func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
  30. assertion.failWrapper.TWithHelper.Helper()
  31. return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
  32. }
  33. func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
  34. assertion.failWrapper.TWithHelper.Helper()
  35. return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
  36. }
  37. func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
  38. assertion.failWrapper.TWithHelper.Helper()
  39. return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
  40. }
  41. func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) string {
  42. switch len(optionalDescription) {
  43. case 0:
  44. return ""
  45. case 1:
  46. if describe, ok := optionalDescription[0].(func() string); ok {
  47. return describe() + "\n"
  48. }
  49. }
  50. return fmt.Sprintf(optionalDescription[0].(string), optionalDescription[1:]...) + "\n"
  51. }
  52. func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool {
  53. matches, err := matcher.Match(assertion.actualInput)
  54. assertion.failWrapper.TWithHelper.Helper()
  55. if err != nil {
  56. description := assertion.buildDescription(optionalDescription...)
  57. assertion.failWrapper.Fail(description+err.Error(), 2+assertion.offset)
  58. return false
  59. }
  60. if matches != desiredMatch {
  61. var message string
  62. if desiredMatch {
  63. message = matcher.FailureMessage(assertion.actualInput)
  64. } else {
  65. message = matcher.NegatedFailureMessage(assertion.actualInput)
  66. }
  67. description := assertion.buildDescription(optionalDescription...)
  68. assertion.failWrapper.Fail(description+message, 2+assertion.offset)
  69. return false
  70. }
  71. return true
  72. }
  73. func (assertion *Assertion) vetExtras(optionalDescription ...interface{}) bool {
  74. success, message := vetExtras(assertion.extra)
  75. if success {
  76. return true
  77. }
  78. description := assertion.buildDescription(optionalDescription...)
  79. assertion.failWrapper.TWithHelper.Helper()
  80. assertion.failWrapper.Fail(description+message, 2+assertion.offset)
  81. return false
  82. }
  83. func vetExtras(extras []interface{}) (bool, string) {
  84. for i, extra := range extras {
  85. if extra != nil {
  86. zeroValue := reflect.Zero(reflect.TypeOf(extra)).Interface()
  87. if !reflect.DeepEqual(zeroValue, extra) {
  88. message := fmt.Sprintf("Unexpected non-nil/non-zero extra argument at index %d:\n\t<%T>: %#v", i+1, extra, extra)
  89. return false, message
  90. }
  91. }
  92. }
  93. return true, ""
  94. }