assertion_validation.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package httpexpect
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. func validateAssertion(failure *AssertionFailure) error {
  7. if len(failure.Errors) == 0 {
  8. return errors.New("AssertionFailure should have non-empty Errors list")
  9. }
  10. for _, err := range failure.Errors {
  11. if err == nil {
  12. return errors.New("AssertionFailure should not have nil in Errors")
  13. } else if refIsNil(err) {
  14. return errors.New("AssertionFailure should not have typed-nil in Errors")
  15. }
  16. }
  17. if err := validateType(failure); err != nil {
  18. return err
  19. }
  20. return nil
  21. }
  22. func validateType(failure *AssertionFailure) error {
  23. switch failure.Type {
  24. case AssertUsage, AssertOperation:
  25. return validateTraits(failure, fieldTraits{
  26. Actual: fieldDenied,
  27. Expected: fieldDenied,
  28. })
  29. case AssertType, AssertNotType,
  30. AssertValid, AssertNotValid,
  31. AssertNil, AssertNotNil,
  32. AssertEmpty, AssertNotEmpty:
  33. return validateTraits(failure, fieldTraits{
  34. Actual: fieldRequired,
  35. Expected: fieldDenied,
  36. })
  37. case AssertEqual, AssertNotEqual,
  38. AssertLt, AssertLe, AssertGt, AssertGe:
  39. return validateTraits(failure, fieldTraits{
  40. Actual: fieldRequired,
  41. Expected: fieldRequired,
  42. })
  43. case AssertInRange, AssertNotInRange:
  44. return validateTraits(failure, fieldTraits{
  45. Actual: fieldRequired,
  46. Expected: fieldRequired,
  47. Range: fieldRequired,
  48. })
  49. case AssertMatchSchema, AssertNotMatchSchema,
  50. AssertMatchPath, AssertNotMatchPath,
  51. AssertMatchRegexp, AssertNotMatchRegexp,
  52. AssertMatchFormat, AssertNotMatchFormat:
  53. return validateTraits(failure, fieldTraits{
  54. Actual: fieldRequired,
  55. Expected: fieldRequired,
  56. })
  57. case AssertContainsKey, AssertNotContainsKey,
  58. AssertContainsElement, AssertNotContainsElement,
  59. AssertContainsSubset, AssertNotContainsSubset:
  60. return validateTraits(failure, fieldTraits{
  61. Actual: fieldRequired,
  62. Expected: fieldOptional,
  63. })
  64. case AssertBelongs, AssertNotBelongs:
  65. return validateTraits(failure, fieldTraits{
  66. Actual: fieldRequired,
  67. Expected: fieldRequired,
  68. List: fieldRequired,
  69. })
  70. }
  71. return fmt.Errorf("unknown assertion type %s", failure.Type)
  72. }
  73. type fieldRequirement uint
  74. const (
  75. fieldOptional fieldRequirement = iota
  76. fieldRequired
  77. fieldDenied
  78. )
  79. type fieldTraits struct {
  80. Actual fieldRequirement
  81. Expected fieldRequirement
  82. Range fieldRequirement
  83. List fieldRequirement
  84. }
  85. func validateTraits(failure *AssertionFailure, traits fieldTraits) error {
  86. switch traits.Actual {
  87. case fieldRequired:
  88. if failure.Actual == nil {
  89. return fmt.Errorf(
  90. "AssertionFailure of type %s should have Actual field",
  91. failure.Type)
  92. }
  93. case fieldDenied:
  94. if failure.Actual != nil {
  95. return fmt.Errorf(
  96. "AssertionFailure of type %s can't have Actual field",
  97. failure.Type)
  98. }
  99. case fieldOptional:
  100. break
  101. }
  102. switch traits.Expected {
  103. case fieldRequired:
  104. if failure.Expected == nil {
  105. return fmt.Errorf(
  106. "AssertionFailure of type %s should have Expected field",
  107. failure.Type)
  108. }
  109. case fieldDenied:
  110. if failure.Expected != nil {
  111. return fmt.Errorf(
  112. "AssertionFailure of type %s can't have Expected field",
  113. failure.Type)
  114. }
  115. case fieldOptional:
  116. break
  117. }
  118. if traits.Range == fieldRequired || traits.Range == fieldOptional {
  119. if failure.Expected != nil {
  120. if _, ok := failure.Expected.Value.(*AssertionRange); ok {
  121. return errors.New(
  122. "AssertionValue should contain AssertionRange, not *AssertionRange")
  123. }
  124. if rng, ok := failure.Expected.Value.(AssertionRange); ok {
  125. if rng.Min == nil {
  126. return errors.New("AssertionRange value should have non-nil Min field")
  127. }
  128. if rng.Max == nil {
  129. return errors.New("AssertionRange value should have non-nil Max field")
  130. }
  131. }
  132. }
  133. }
  134. switch traits.Range {
  135. case fieldRequired:
  136. if failure.Expected == nil {
  137. return fmt.Errorf(
  138. "AssertionFailure of type %s should have Expected field",
  139. failure.Type)
  140. }
  141. if _, ok := failure.Expected.Value.(AssertionRange); !ok {
  142. return fmt.Errorf(
  143. "AssertionFailure of type %s"+
  144. " should have Expected field with AssertionRange value",
  145. failure.Type)
  146. }
  147. case fieldDenied:
  148. panic("unsupported")
  149. case fieldOptional:
  150. break
  151. }
  152. if traits.List == fieldRequired || traits.List == fieldOptional {
  153. if failure.Expected != nil {
  154. if _, ok := failure.Expected.Value.(*AssertionList); ok {
  155. return errors.New(
  156. "AssertionValue should contain AssertionList, not *AssertionList")
  157. }
  158. if lst, ok := failure.Expected.Value.(AssertionList); ok {
  159. if len(lst) == 0 {
  160. return errors.New("AssertionList should be non-empty")
  161. }
  162. }
  163. }
  164. }
  165. switch traits.List {
  166. case fieldRequired:
  167. if failure.Expected == nil {
  168. return fmt.Errorf(
  169. "AssertionFailure of type %s should have Expected field",
  170. failure.Type)
  171. }
  172. if _, ok := failure.Expected.Value.(AssertionList); !ok {
  173. return fmt.Errorf(
  174. "AssertionFailure of type %s"+
  175. " should have Expected field with AssertionList value",
  176. failure.Type)
  177. }
  178. case fieldDenied:
  179. panic("unsupported")
  180. case fieldOptional:
  181. break
  182. }
  183. return nil
  184. }