Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Violations usages from test harness #262

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ proto_library(
strip_import_prefix = "/proto/protovalidate-testing",
visibility = ["//visibility:public"],
deps = [
"//proto/protovalidate/buf/validate:validate_proto",
"@com_google_protobuf//:any_proto",
"@com_google_protobuf//:descriptor_proto",
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ syntax = "proto3";

package buf.validate.conformance.harness;

import "buf/validate/validate.proto";
import "google/protobuf/any.proto";
import "google/protobuf/descriptor.proto";

Expand All @@ -40,7 +39,7 @@ message TestResult {
// success is true if the test succeeded.
bool success = 1;
// validation_error is the error if the test failed due to validation errors.
Violations validation_error = 2;
ValidationError validation_error = 2;
// compilation_error is the error if the test failed due to compilation errors.
string compilation_error = 3;
// runtime_error is the error if the test failed due to runtime errors.
Expand All @@ -49,3 +48,38 @@ message TestResult {
string unexpected_error = 5;
}
}

// ValidationError is the result if the test failed due to validation errors.
message ValidationError {
// `violations` is a repeated field that contains all the `Violation` messages corresponding to the violations detected.
repeated Violation violations = 1;
}

// `Violation` represents a single instance where a validation rule, expressed
// as a `Constraint`, was not met. It provides information about the field that
// caused the violation, the specific constraint that wasn't fulfilled, and a
// human-readable error message.
//
// ```json
// {
// "fieldPath": "bar",
// "constraintId": "foo.bar",
// "message": "bar must be greater than 0"
// }
// ```
message Violation {
// `field_path` is a machine-readable identifier that points to the specific field that failed the validation.
// This could be a nested field, in which case the path will include all the parent fields leading to the actual field that caused the violation.
optional string field_path = 1;

// `constraint_id` is the unique identifier of the `Constraint` that was not fulfilled.
// This is the same `id` that was specified in the `Constraint` message, allowing easy tracing of which rule was violated.
optional string constraint_id = 2;

// `message` is a human-readable error message that describes the nature of the violation.
// This can be the default error message from the violated `Constraint`, or it can be a custom message that gives more context about the violation.
optional string message = 3;

// `for_key` indicates whether the violation was caused by a map key, rather than a value.
optional bool for_key = 4;
}
372 changes: 279 additions & 93 deletions tools/internal/gen/buf/validate/conformance/harness/harness.pb.go

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions tools/protovalidate-conformance/internal/cases/cases_any.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ package cases
import (
"time"

"github.com/bufbuild/protovalidate/tools/internal/gen/buf/validate"
"github.com/bufbuild/protovalidate/tools/internal/gen/buf/validate/conformance/cases"
"github.com/bufbuild/protovalidate/tools/internal/gen/buf/validate/conformance/harness"
"github.com/bufbuild/protovalidate/tools/protovalidate-conformance/internal/results"
"github.com/bufbuild/protovalidate/tools/protovalidate-conformance/internal/suites"
"google.golang.org/protobuf/proto"
Expand Down Expand Up @@ -60,12 +60,12 @@ func anySuite() suites.Suite {
"in/invalid/known": {
Message: &cases.AnyIn{Val: tsAny},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("any.in")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("any.in")}),
},
"in/invalid/unknown": {
Message: &cases.AnyIn{Val: fooAny},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("any.in")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("any.in")}),
},
"not_in/valid/known": {
Message: &cases.AnyNotIn{Val: durAny},
Expand All @@ -82,7 +82,7 @@ func anySuite() suites.Suite {
"not_in/invalid/known": {
Message: &cases.AnyNotIn{Val: tsAny},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("any.not_in")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("any.not_in")}),
},
"required/valid/known": {
Message: &cases.AnyRequired{Val: tsAny},
Expand All @@ -95,7 +95,7 @@ func anySuite() suites.Suite {
"require/invalid": {
Message: &cases.AnyRequired{},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("required")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("required")}),
},
}
}
6 changes: 3 additions & 3 deletions tools/protovalidate-conformance/internal/cases/cases_bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
package cases

import (
"github.com/bufbuild/protovalidate/tools/internal/gen/buf/validate"
"github.com/bufbuild/protovalidate/tools/internal/gen/buf/validate/conformance/cases"
"github.com/bufbuild/protovalidate/tools/internal/gen/buf/validate/conformance/harness"
"github.com/bufbuild/protovalidate/tools/protovalidate-conformance/internal/results"
"github.com/bufbuild/protovalidate/tools/protovalidate-conformance/internal/suites"
"google.golang.org/protobuf/proto"
Expand All @@ -35,7 +35,7 @@ func boolSuite() suites.Suite {
"const/true/invalid": {
Message: &cases.BoolConstTrue{Val: false},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bool.const")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bool.const")}),
},
"const/false/valid": {
Message: &cases.BoolConstFalse{Val: false},
Expand All @@ -44,7 +44,7 @@ func boolSuite() suites.Suite {
"const/false/invalid": {
Message: &cases.BoolConstFalse{Val: true},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bool.const")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bool.const")}),
},
"example/valid": {
Message: &cases.BoolExample{Val: true},
Expand Down
44 changes: 22 additions & 22 deletions tools/protovalidate-conformance/internal/cases/cases_bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
package cases

import (
"github.com/bufbuild/protovalidate/tools/internal/gen/buf/validate"
"github.com/bufbuild/protovalidate/tools/internal/gen/buf/validate/conformance/cases"
"github.com/bufbuild/protovalidate/tools/internal/gen/buf/validate/conformance/harness"
"github.com/bufbuild/protovalidate/tools/protovalidate-conformance/internal/results"
"github.com/bufbuild/protovalidate/tools/protovalidate-conformance/internal/suites"
"google.golang.org/protobuf/proto"
Expand All @@ -35,7 +35,7 @@ func bytesSuite() suites.Suite {
"const/invalid": {
Message: &cases.BytesConst{Val: []byte("bar")},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bytes.const")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bytes.const")}),
},
"in/valid": {
Message: &cases.BytesIn{Val: []byte("bar")},
Expand All @@ -44,7 +44,7 @@ func bytesSuite() suites.Suite {
"in/invalid": {
Message: &cases.BytesIn{Val: []byte("quux")},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bytes.in")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bytes.in")}),
},
"not_in/valid": {
Message: &cases.BytesNotIn{Val: []byte("quux")},
Expand All @@ -53,7 +53,7 @@ func bytesSuite() suites.Suite {
"not_in/invalid": {
Message: &cases.BytesNotIn{Val: []byte("fizz")},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bytes.not_in")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bytes.not_in")}),
},
"len/valid": {
Message: &cases.BytesLen{Val: []byte("baz")},
Expand All @@ -62,12 +62,12 @@ func bytesSuite() suites.Suite {
"len/invalid/less": {
Message: &cases.BytesLen{Val: []byte("go")},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bytes.len")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bytes.len")}),
},
"len/invalid/greater": {
Message: &cases.BytesLen{Val: []byte("fizz")},
Expected: results.Violations(
&validate.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bytes.len")}),
&harness.Violation{FieldPath: proto.String("val"), ConstraintId: proto.String("bytes.len")}),
},
"min_len/valid/equal": {
Message: &cases.BytesMinLen{Val: []byte("baz")},
Expand All @@ -79,7 +79,7 @@ func bytesSuite() suites.Suite {
},
"min_len/invalid": {
Message: &cases.BytesMinLen{Val: []byte("go")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.min_len"),
Message: proto.String("value length must be at least 3 bytes"),
Expand All @@ -95,7 +95,7 @@ func bytesSuite() suites.Suite {
},
"max_len/invalid": {
Message: &cases.BytesMaxLen{Val: []byte("1234567890")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.max_len"),
Message: proto.String("value must be at most 5 bytes"),
Expand All @@ -115,15 +115,15 @@ func bytesSuite() suites.Suite {
},
"min/max_len/invalid/below": {
Message: &cases.BytesMinMaxLen{Val: []byte("go")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.min_len"),
Message: proto.String("value length must be at least 3 bytes"),
}),
},
"min/max_len/invalid/above": {
Message: &cases.BytesMinMaxLen{Val: []byte("validate")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.max_len"),
Message: proto.String("value must be at most 5 bytes"),
Expand All @@ -135,7 +135,7 @@ func bytesSuite() suites.Suite {
},
"equal/min_len/max_len/invalid": {
Message: &cases.BytesEqualMinMaxLen{Val: []byte("validate")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.max_len"),
Message: proto.String("value must be at most 5 bytes"),
Expand All @@ -147,15 +147,15 @@ func bytesSuite() suites.Suite {
},
"pattern/invalid": {
Message: &cases.BytesPattern{Val: []byte("你好你好")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.pattern"),
Message: proto.String("value must match regex pattern `^[\\x00-\\x7F]+$`"),
}),
},
"pattern/invalid/empty": {
Message: &cases.BytesPattern{Val: []byte("")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.pattern"),
Message: proto.String("value must match regex pattern `^[\\x00-\\x7F]+$`"),
Expand All @@ -175,7 +175,7 @@ func bytesSuite() suites.Suite {
},
"prefix/invalid": {
Message: &cases.BytesPrefix{Val: []byte("bar")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.prefix"),
Message: proto.String("value does not have prefix 99"),
Expand All @@ -191,7 +191,7 @@ func bytesSuite() suites.Suite {
},
"contains/invalid": {
Message: &cases.BytesContains{Val: []byte("candy bazs")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.contains"),
Message: proto.String("value does not contain 626172"),
Expand All @@ -207,15 +207,15 @@ func bytesSuite() suites.Suite {
},
"suffix/invalid": {
Message: &cases.BytesSuffix{Val: []byte("foobar")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.suffix"),
Message: proto.String("value does not have suffix 62757a7a"),
}),
},
"suffix/case_sensitive/invalid": {
Message: &cases.BytesSuffix{Val: []byte("FooBaz")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.suffix"),
Message: proto.String("value does not have suffix 62757a7a"),
Expand All @@ -231,7 +231,7 @@ func bytesSuite() suites.Suite {
},
"IP/invalid": {
Message: &cases.BytesIP{Val: []byte("foobar")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.ip"),
Message: proto.String("value must be a valid IP address"),
Expand All @@ -247,7 +247,7 @@ func bytesSuite() suites.Suite {
},
"IPv4/invalid": {
Message: &cases.BytesIPv4{Val: []byte("foobar")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.ipv4"),
Message: proto.String("value must be a valid IPv4 address"),
Expand All @@ -259,7 +259,7 @@ func bytesSuite() suites.Suite {
},
"IPv4/invalid/v6": {
Message: &cases.BytesIPv4{Val: []byte("\x20\x01\x0D\xB8\x85\xA3\x00\x00\x00\x00\x8A\x2E\x03\x70\x73\x34")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.ipv4"),
Message: proto.String("value must be a valid IPv4 address"),
Expand All @@ -271,7 +271,7 @@ func bytesSuite() suites.Suite {
},
"IPv6/invalid": {
Message: &cases.BytesIPv6{Val: []byte("fooar")},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.ipv6"),
Message: proto.String("value must be a valid IPv6 address"),
Expand All @@ -283,7 +283,7 @@ func bytesSuite() suites.Suite {
},
"IPv6/invalid/v4": {
Message: &cases.BytesIPv6{Val: []byte{0xC0, 0xA8, 0x00, 0x01}},
Expected: results.Violations(&validate.Violation{
Expected: results.Violations(&harness.Violation{
FieldPath: proto.String("val"),
ConstraintId: proto.String("bytes.ipv6"),
}),
Expand Down
Loading