Last active
July 9, 2021 06:43
-
-
Save rodaine/0b65e59207da0b799214564ec33e5087 to your computer and use it in GitHub Desktop.
Triage exploration for https://github.com/envoyproxy/protoc-gen-validate/pull/485
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Code generated by protoc-gen-go. DO NOT EDIT. | |
// versions: | |
// protoc-gen-go v1.27.1-devel | |
// protoc v3.17.3 | |
// source: foo.proto | |
package foo | |
import ( | |
_ "github.com/envoyproxy/protoc-gen-validate/validate" | |
protoreflect "google.golang.org/protobuf/reflect/protoreflect" | |
protoimpl "google.golang.org/protobuf/runtime/protoimpl" | |
timestamppb "google.golang.org/protobuf/types/known/timestamppb" | |
reflect "reflect" | |
sync "sync" | |
) | |
const ( | |
// Verify that this generated code is sufficiently up-to-date. | |
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) | |
// Verify that runtime/protoimpl is sufficiently up-to-date. | |
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) | |
) | |
type MyThingy struct { | |
state protoimpl.MessageState | |
sizeCache protoimpl.SizeCache | |
unknownFields protoimpl.UnknownFields | |
// Types that are assignable to Type: | |
// *MyThingy_StringValue | |
// *MyThingy_Int64Value | |
// *MyThingy_DoubleValue | |
// *MyThingy_BooleanValue | |
Type isMyThingy_Type `protobuf_oneof:"type"` | |
LastUpdated *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"` | |
} | |
func (x *MyThingy) Reset() { | |
*x = MyThingy{} | |
if protoimpl.UnsafeEnabled { | |
mi := &file_foo_proto_msgTypes[0] | |
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
ms.StoreMessageInfo(mi) | |
} | |
} | |
func (x *MyThingy) String() string { | |
return protoimpl.X.MessageStringOf(x) | |
} | |
func (*MyThingy) ProtoMessage() {} | |
func (x *MyThingy) ProtoReflect() protoreflect.Message { | |
mi := &file_foo_proto_msgTypes[0] | |
if protoimpl.UnsafeEnabled && x != nil { | |
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
if ms.LoadMessageInfo() == nil { | |
ms.StoreMessageInfo(mi) | |
} | |
return ms | |
} | |
return mi.MessageOf(x) | |
} | |
// Deprecated: Use MyThingy.ProtoReflect.Descriptor instead. | |
func (*MyThingy) Descriptor() ([]byte, []int) { | |
return file_foo_proto_rawDescGZIP(), []int{0} | |
} | |
func (m *MyThingy) GetType() isMyThingy_Type { | |
if m != nil { | |
return m.Type | |
} | |
return nil | |
} | |
func (x *MyThingy) GetStringValue() string { | |
if x, ok := x.GetType().(*MyThingy_StringValue); ok { | |
return x.StringValue | |
} | |
return "" | |
} | |
func (x *MyThingy) GetInt64Value() int64 { | |
if x, ok := x.GetType().(*MyThingy_Int64Value); ok { | |
return x.Int64Value | |
} | |
return 0 | |
} | |
func (x *MyThingy) GetDoubleValue() float64 { | |
if x, ok := x.GetType().(*MyThingy_DoubleValue); ok { | |
return x.DoubleValue | |
} | |
return 0 | |
} | |
func (x *MyThingy) GetBooleanValue() bool { | |
if x, ok := x.GetType().(*MyThingy_BooleanValue); ok { | |
return x.BooleanValue | |
} | |
return false | |
} | |
func (x *MyThingy) GetLastUpdated() *timestamppb.Timestamp { | |
if x != nil { | |
return x.LastUpdated | |
} | |
return nil | |
} | |
type isMyThingy_Type interface { | |
isMyThingy_Type() | |
} | |
type MyThingy_StringValue struct { | |
StringValue string `protobuf:"bytes,2,opt,name=string_value,json=stringValue,proto3,oneof"` | |
} | |
type MyThingy_Int64Value struct { | |
Int64Value int64 `protobuf:"varint,4,opt,name=int64_value,json=int64Value,proto3,oneof"` | |
} | |
type MyThingy_DoubleValue struct { | |
DoubleValue float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue,proto3,oneof"` | |
} | |
type MyThingy_BooleanValue struct { | |
BooleanValue bool `protobuf:"varint,8,opt,name=boolean_value,json=booleanValue,proto3,oneof"` | |
} | |
func (*MyThingy_StringValue) isMyThingy_Type() {} | |
func (*MyThingy_Int64Value) isMyThingy_Type() {} | |
func (*MyThingy_DoubleValue) isMyThingy_Type() {} | |
func (*MyThingy_BooleanValue) isMyThingy_Type() {} | |
var File_foo_proto protoreflect.FileDescriptor | |
var file_foo_proto_rawDesc = []byte{ | |
0x0a, 0x09, 0x66, 0x6f, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x66, 0x6f, 0x6f, | |
0x1a, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, | |
0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, | |
0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, | |
0x6f, 0x22, 0xf6, 0x01, 0x0a, 0x08, 0x4d, 0x79, 0x54, 0x68, 0x69, 0x6e, 0x67, 0x79, 0x12, 0x2f, | |
0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, | |
0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x72, 0x05, 0x10, 0x01, 0x18, 0xe8, 0x07, | |
0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, | |
0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, | |
0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, | |
0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, | |
0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, | |
0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, 0x0d, 0x62, 0x6f, 0x6f, 0x6c, 0x65, | |
0x61, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, | |
0x52, 0x0c, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, | |
0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x09, | |
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, | |
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, | |
0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, 0x0b, 0x0a, | |
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x42, 0x18, 0x5a, 0x16, 0x67, 0x69, | |
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x6f, 0x64, 0x61, 0x69, 0x6e, 0x65, | |
0x2f, 0x66, 0x6f, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | |
} | |
var ( | |
file_foo_proto_rawDescOnce sync.Once | |
file_foo_proto_rawDescData = file_foo_proto_rawDesc | |
) | |
func file_foo_proto_rawDescGZIP() []byte { | |
file_foo_proto_rawDescOnce.Do(func() { | |
file_foo_proto_rawDescData = protoimpl.X.CompressGZIP(file_foo_proto_rawDescData) | |
}) | |
return file_foo_proto_rawDescData | |
} | |
var file_foo_proto_msgTypes = make([]protoimpl.MessageInfo, 1) | |
var file_foo_proto_goTypes = []interface{}{ | |
(*MyThingy)(nil), // 0: foo.MyThingy | |
(*timestamppb.Timestamp)(nil), // 1: google.protobuf.Timestamp | |
} | |
var file_foo_proto_depIdxs = []int32{ | |
1, // 0: foo.MyThingy.last_updated:type_name -> google.protobuf.Timestamp | |
1, // [1:1] is the sub-list for method output_type | |
1, // [1:1] is the sub-list for method input_type | |
1, // [1:1] is the sub-list for extension type_name | |
1, // [1:1] is the sub-list for extension extendee | |
0, // [0:1] is the sub-list for field type_name | |
} | |
func init() { file_foo_proto_init() } | |
func file_foo_proto_init() { | |
if File_foo_proto != nil { | |
return | |
} | |
if !protoimpl.UnsafeEnabled { | |
file_foo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { | |
switch v := v.(*MyThingy); i { | |
case 0: | |
return &v.state | |
case 1: | |
return &v.sizeCache | |
case 2: | |
return &v.unknownFields | |
default: | |
return nil | |
} | |
} | |
} | |
file_foo_proto_msgTypes[0].OneofWrappers = []interface{}{ | |
(*MyThingy_StringValue)(nil), | |
(*MyThingy_Int64Value)(nil), | |
(*MyThingy_DoubleValue)(nil), | |
(*MyThingy_BooleanValue)(nil), | |
} | |
type x struct{} | |
out := protoimpl.TypeBuilder{ | |
File: protoimpl.DescBuilder{ | |
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | |
RawDescriptor: file_foo_proto_rawDesc, | |
NumEnums: 0, | |
NumMessages: 1, | |
NumExtensions: 0, | |
NumServices: 0, | |
}, | |
GoTypes: file_foo_proto_goTypes, | |
DependencyIndexes: file_foo_proto_depIdxs, | |
MessageInfos: file_foo_proto_msgTypes, | |
}.Build() | |
File_foo_proto = out.File | |
file_foo_proto_rawDesc = nil | |
file_foo_proto_goTypes = nil | |
file_foo_proto_depIdxs = nil | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Code generated by protoc-gen-validate. DO NOT EDIT. | |
// source: foo.proto | |
package foo | |
import ( | |
"bytes" | |
"errors" | |
"fmt" | |
"net" | |
"net/mail" | |
"net/url" | |
"regexp" | |
"strings" | |
"time" | |
"unicode/utf8" | |
"google.golang.org/protobuf/types/known/anypb" | |
) | |
// ensure the imports are used | |
var ( | |
_ = bytes.MinRead | |
_ = errors.New("") | |
_ = fmt.Print | |
_ = utf8.UTFMax | |
_ = (*regexp.Regexp)(nil) | |
_ = (*strings.Reader)(nil) | |
_ = net.IPv4len | |
_ = time.Duration(0) | |
_ = (*url.URL)(nil) | |
_ = (*mail.Address)(nil) | |
_ = anypb.Any{} | |
) | |
// Validate checks the field values on MyThingy with the rules defined in the | |
// proto definition for this message. If any rules are violated, the first | |
// error encountered is returned, or nil if there are no violations. | |
func (m *MyThingy) Validate() error { | |
return m.validate(false) | |
} | |
// ValidateAll checks the field values on MyThingy with the rules defined in | |
// the proto definition for this message. If any rules are violated, the | |
// result is a list of violation errors wrapped in MyThingyMultiError, or nil | |
// if none found. | |
func (m *MyThingy) ValidateAll() error { | |
return m.validate(true) | |
} | |
func (m *MyThingy) validate(all bool) error { | |
if m == nil { | |
return nil | |
} | |
var errors []error | |
if all { | |
switch v := interface{}(m.GetLastUpdated()).(type) { | |
case interface{ ValidateAll() error }: | |
if err := v.ValidateAll(); err != nil { | |
errors = append(errors, MyThingyValidationError{ | |
field: "LastUpdated", | |
reason: "embedded message failed validation", | |
cause: err, | |
}) | |
} | |
case interface{ Validate() error }: | |
if err := v.Validate(); err != nil { | |
errors = append(errors, MyThingyValidationError{ | |
field: "LastUpdated", | |
reason: "embedded message failed validation", | |
cause: err, | |
}) | |
} | |
} | |
} else if v, ok := interface{}(m.GetLastUpdated()).(interface{ Validate() error }); ok { | |
if err := v.Validate(); err != nil { | |
return MyThingyValidationError{ | |
field: "LastUpdated", | |
reason: "embedded message failed validation", | |
cause: err, | |
} | |
} | |
} | |
switch m.Type.(type) { | |
case *MyThingy_StringValue: | |
if l := utf8.RuneCountInString(m.GetStringValue()); l < 1 || l > 1000 { | |
err := MyThingyValidationError{ | |
field: "StringValue", | |
reason: "value length must be between 1 and 1000 runes, inclusive", | |
} | |
if !all { | |
return err | |
} | |
errors = append(errors, err) | |
} | |
case *MyThingy_Int64Value: | |
// no validation rules for Int64Value | |
case *MyThingy_DoubleValue: | |
// no validation rules for DoubleValue | |
case *MyThingy_BooleanValue: | |
// no validation rules for BooleanValue | |
default: | |
err := MyThingyValidationError{ | |
field: "Type", | |
reason: "value is required", | |
} | |
if !all { | |
return err | |
} | |
errors = append(errors, err) | |
} | |
if len(errors) > 0 { | |
return MyThingyMultiError(errors) | |
} | |
return nil | |
} | |
// MyThingyMultiError is an error wrapping multiple validation errors returned | |
// by MyThingy.ValidateAll() if the designated constraints aren't met. | |
type MyThingyMultiError []error | |
// Error returns a concatenation of all the error messages it wraps. | |
func (m MyThingyMultiError) Error() string { | |
var msgs []string | |
for _, err := range m { | |
msgs = append(msgs, err.Error()) | |
} | |
return strings.Join(msgs, "; ") | |
} | |
// AllErrors returns a list of validation violation errors. | |
func (m MyThingyMultiError) AllErrors() []error { return m } | |
// MyThingyValidationError is the validation error returned by | |
// MyThingy.Validate if the designated constraints aren't met. | |
type MyThingyValidationError struct { | |
field string | |
reason string | |
cause error | |
key bool | |
} | |
// Field function returns field value. | |
func (e MyThingyValidationError) Field() string { return e.field } | |
// Reason function returns reason value. | |
func (e MyThingyValidationError) Reason() string { return e.reason } | |
// Cause function returns cause value. | |
func (e MyThingyValidationError) Cause() error { return e.cause } | |
// Key function returns key value. | |
func (e MyThingyValidationError) Key() bool { return e.key } | |
// ErrorName returns error name. | |
func (e MyThingyValidationError) ErrorName() string { return "MyThingyValidationError" } | |
// Error satisfies the builtin error interface | |
func (e MyThingyValidationError) Error() string { | |
cause := "" | |
if e.cause != nil { | |
cause = fmt.Sprintf(" | caused by: %v", e.cause) | |
} | |
key := "" | |
if e.key { | |
key = "key for " | |
} | |
return fmt.Sprintf( | |
"invalid %sMyThingy.%s: %s%s", | |
key, | |
e.field, | |
e.reason, | |
cause) | |
} | |
var _ error = MyThingyValidationError{} | |
var _ interface { | |
Field() string | |
Reason() string | |
Key() bool | |
Cause() error | |
ErrorName() string | |
} = MyThingyValidationError{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// protoc --go_out="paths=source_relative:." --validate_out="lang=go,paths=source_relative:." foo.proto | |
syntax="proto3"; | |
package foo; | |
import "validate.proto"; | |
import "google/protobuf/timestamp.proto"; | |
option go_package = "github.com/rodaine/foo"; | |
message MyThingy { | |
oneof type { | |
option (validate.required) = true; | |
string string_value = 2 [(validate.rules).string = {min_len: 1, max_len: 1000}]; | |
int64 int64_value = 4; | |
double double_value = 6; | |
bool boolean_value = 8; | |
} | |
google.protobuf.Timestamp last_updated = 9; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package foo | |
import ( | |
"google.golang.org/protobuf/types/known/timestamppb" | |
"testing" | |
) | |
func TestMyThingy(t *testing.T) { | |
tests := []struct{ | |
name string | |
in *MyThingy | |
valid bool | |
}{ | |
{ | |
"with type", | |
&MyThingy{ | |
Type: &MyThingy_Int64Value{Int64Value: 123}, | |
LastUpdated: timestamppb.Now(), | |
}, | |
true, | |
}, | |
{ | |
"with nil type", | |
&MyThingy{ | |
Type: nil, | |
LastUpdated: timestamppb.Now(), | |
}, | |
false, | |
}, | |
{ | |
"no type", | |
&MyThingy{LastUpdated: timestamppb.Now()}, | |
false, | |
}, | |
{ | |
"nil in", | |
nil, | |
true, | |
}, | |
{ | |
"typed nil", | |
&MyThingy{Type: (*MyThingy_Int64Value)(nil)}, | |
false, | |
}, | |
} | |
for _, test := range tests { | |
t.Run(test.name, func(t *testing.T) { | |
err := test.in.Validate() | |
if test.valid && err != nil { | |
t.Fatalf("wanted no error, got %v", err) | |
} else if !test.valid && err == nil { | |
t.Fatal("wanted error, got nil") | |
} | |
}) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module github.com/rodaine/foo | |
go 1.16 | |
require ( | |
github.com/envoyproxy/protoc-gen-validate v0.6.1 | |
google.golang.org/protobuf v1.27.1 | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
→ go test -v . | |
=== RUN TestMyThingy | |
=== RUN TestMyThingy/with_type | |
=== RUN TestMyThingy/with_nil_type | |
=== RUN TestMyThingy/no_type | |
=== RUN TestMyThingy/nil_in | |
=== RUN TestMyThingy/typed_nil | |
foo_test.go:53: wanted error, got nil | |
--- FAIL: TestMyThingy (0.00s) | |
--- PASS: TestMyThingy/with_type (0.00s) | |
--- PASS: TestMyThingy/with_nil_type (0.00s) | |
--- PASS: TestMyThingy/no_type (0.00s) | |
--- PASS: TestMyThingy/nil_in (0.00s) | |
--- FAIL: TestMyThingy/typed_nil (0.00s) | |
FAIL | |
FAIL github.com/rodaine/foo 0.105s | |
FAIL |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Generated with versions: