harness.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "log"
  6. "os"
  7. "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go"
  8. _ "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/go"
  9. _ "github.com/envoyproxy/protoc-gen-validate/tests/harness/cases/other_package/go"
  10. "github.com/envoyproxy/protoc-gen-validate/tests/harness/go"
  11. "google.golang.org/protobuf/proto"
  12. )
  13. func main() {
  14. b, err := ioutil.ReadAll(os.Stdin)
  15. checkErr(err)
  16. tc := new(harness.TestCase)
  17. checkErr(proto.Unmarshal(b, tc))
  18. msg, err := tc.Message.UnmarshalNew()
  19. checkErr(err)
  20. _, isIgnored := msg.(*cases.MessageIgnored)
  21. vMsg, hasValidate := msg.(interface {
  22. Validate() error
  23. })
  24. vAllMsg, hasValidateAll := msg.(interface {
  25. ValidateAll() error
  26. })
  27. var multierr error
  28. if isIgnored {
  29. // confirm that ignored messages don't have a validate method
  30. if hasValidate {
  31. checkErr(fmt.Errorf("ignored message %T has Validate() method", msg))
  32. }
  33. if hasValidateAll {
  34. checkErr(fmt.Errorf("ignored message %T has ValidateAll() method", msg))
  35. }
  36. } else if !hasValidate {
  37. checkErr(fmt.Errorf("non-ignored message %T is missing Validate()", msg))
  38. } else if !hasValidateAll {
  39. checkErr(fmt.Errorf("non-ignored message %T is missing ValidateAll()", msg))
  40. } else {
  41. err = vMsg.Validate()
  42. multierr = vAllMsg.ValidateAll()
  43. }
  44. checkValid(err, multierr)
  45. }
  46. type hasAllErrors interface{ AllErrors() []error }
  47. type hasCause interface{ Cause() error }
  48. func checkValid(err, multierr error) {
  49. if err == nil && multierr == nil {
  50. resp(&harness.TestResult{Valid: true})
  51. return
  52. }
  53. if (err != nil) != (multierr != nil) {
  54. checkErr(fmt.Errorf("different verdict of Validate() [%v] vs. ValidateAll() [%v]", err, multierr))
  55. return
  56. }
  57. // Extract the message from "lazy" Validate(), for comparison with ValidateAll()
  58. rootCause := err
  59. for {
  60. caused, ok := rootCause.(hasCause)
  61. if !ok || caused.Cause() == nil {
  62. break
  63. }
  64. rootCause = caused.Cause()
  65. }
  66. // Retrieve the messages from "extensive" ValidateAll() and compare first one with the "lazy" message
  67. m, ok := multierr.(hasAllErrors)
  68. if !ok {
  69. checkErr(fmt.Errorf("ValidateAll() returned error without AllErrors() method: %#v", multierr))
  70. return
  71. }
  72. reasons := mergeReasons(nil, m)
  73. if rootCause.Error() != reasons[0] {
  74. checkErr(fmt.Errorf("different first message, Validate()==%q, ValidateAll()==%q", rootCause.Error(), reasons[0]))
  75. return
  76. }
  77. resp(&harness.TestResult{Reasons: reasons})
  78. }
  79. func mergeReasons(reasons []string, multi hasAllErrors) []string {
  80. for _, err := range multi.AllErrors() {
  81. caused, ok := err.(hasCause)
  82. if ok && caused.Cause() != nil {
  83. err = caused.Cause()
  84. }
  85. multi, ok := err.(hasAllErrors)
  86. if ok {
  87. reasons = mergeReasons(reasons, multi)
  88. } else {
  89. reasons = append(reasons, err.Error())
  90. }
  91. }
  92. return reasons
  93. }
  94. func checkErr(err error) {
  95. if err == nil {
  96. return
  97. }
  98. resp(&harness.TestResult{
  99. Error: true,
  100. Reasons: []string{err.Error()},
  101. })
  102. }
  103. func resp(result *harness.TestResult) {
  104. if b, err := proto.Marshal(result); err != nil {
  105. log.Fatalf("could not marshal response: %v", err)
  106. } else if _, err = os.Stdout.Write(b); err != nil {
  107. log.Fatalf("could not write response: %v", err)
  108. }
  109. os.Exit(0)
  110. }