-
Notifications
You must be signed in to change notification settings - Fork 810
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
Feature/96 validators #100
Conversation
@@ -67,6 +67,8 @@ extend google.protobuf.FileOptions { | |||
optional bool goproto_extensions_map_all = 63025; | |||
optional bool goproto_unrecognized_all = 63026; | |||
optional bool gogoproto_import = 63027; | |||
|
|||
optional bool validator_all = 63028; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will you use file level validation for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally thought about doing a validator for every file. But that's not needed since the Validator
interface was declared.
Done some major changes:
Still need some hints as to how to test this? Manually written tests in |
} | ||
} | ||
|
||
func (p *plugin) generateProto2Message(file *generator.FileDescriptor, message *generator.Descriptor) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to fold proto2 and proto3 into one method generateMethod with some ifs for proto3, check some of the other plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did that initially, but the code turned out incredibly spaghetti due to the proto2
handling of nullable
. I decided to split it up to make it easier to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should check again.
} else if nullable && !proto3 {
Manually written tests in test/validator is a start. How about using the populate plugin. I actually can't think of a way to do this more automatically :( |
If you only support limited functions that have some duality, checking and random generation then you could extend the populate plugin to only generate valid messages. |
Can you provide pointers to examples of how to use the |
In https://github.com/gogo/protobuf/blob/master/test/example/example.proto you can see
This generates a NewPopulatedA function Which is used by the generated tests |
The amount of specific functions could become quite large. For each function a new extension will be needed. Check for example the amount of functions that json schema has: http://json-schema.org/latest/json-schema-validation.html |
Re json schema bloat:
On top of that the only thing I can think anyone would need is I genuinely think that this, coupled with the |
Added manual tests. They're not well broken up into individual per-field functions, but they do test all the edge cases I could think of. |
Cool tests. I had another thought.
Then I started thinking more about unmarshaling. Example:
What do you think? |
Apologies for the delay, work got in the way. :( It feels like custom types would be quite intrusive in the normal proto3 flow that people get used to when reading official docs. I think keeping it as a clear extension that deals with validation is clearer. However, I do like the idea of extracting the Also, as we build more and more services, this becomes an ever more important feature for us. Can we treat the current implementation as an MVP (with a possible addition of floats), and later maybe add custom types? For now I'm kinda puzzled why this change causes the maps test to fail:
:( |
No problem. Regarding clearer docs, yes. We could just find a new name for required like for example, req, proto2required, etc. MVP is great for proprietary code, when you can keep a handle on all your users, but for an open source tool and library I am quite scared to apply the same logic. I think at least the vision needs to be clear and it should be known how backwards compatibility will not be broken. Regarding the failed test, please try getting the newest master. |
0b4bdd7
to
3626925
Compare
Thanks for the response Walter, apologies I haven't got back to you in a while.. vacation 😎 I've rebased it on current After a week I'll come back and report progress and possibly implement the customtype and customname tests. As for |
No problem hope you enjoyed the holiday :) I look forward to hearing about your experiences. customtype, customname and casttype tests sound good :) In my opinion required only for submessages is a hack, sorry, but we have discussed a perfectly full feature where required checking happens during unmarshaling, just as it is being done for proto2 required. |
e619e86
to
e4838ff
Compare
e4838ff
to
9aa83b2
Compare
Sorry for the long time without response. The If you're interested in me upstreaming this work, please provide pointers as to what improvements you'd like to see other than customtype/cuystomname tests. :) |
Great to hear from you again :) Did you find that you needed any other functions, did your users wish they could do more validation? I think the best would be to start with promoting msg_exists to something resembling the proto2 required functionality. This should be a totally separate pull request. That way it will make my life a lot easier. Would this be possible for you? Next you have the regex, min and max functions, which are pure validators and nothing more. This is where some tests are needed: Please tell me if I have missed something? |
Seems there is at least one more person interested in validating protobufs golang/protobuf#52 |
Thanks @awalterschulze for pointing me here. I would like to note some general thoughts here. @mwitkow Please do not see the them as critique towards your impressive work 👏 , but as suggestions for the general route. I think we have the same idea: define protobuf messages, use them as our models for gRPC based services (and other "stuff") and have easy means validating messages. So my idea was to leverage existing validation solutions. Those are (almost) all based on struct tags and reflection. So I searched to find a way to add custom struct tags on generation, which is a feature request denied in golang/protobuf#52. This approach would have quite some advantages, however:
The only problem I see is to prevent the need to have a protobuf extension which will only make sense with gogo/protobuf's generator. I am not too sure here, but my thought from a user's point of view is to have comments with a semantic meaning, much like My vision (and top priority on my wishlist for Santa 😍 ) is something like this syntax = "proto3";
message Foo {
string Id = 1; //gogo:tags `bson:"_id" valid:"hexadecimal, required" foo:"bar"`
} and have those tags added to the generated code: type Foo struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omit empty" bson:"_id" valid:"hexadecimal, required" foo:"bar"`
} which would allow easy validation (using govalidator, for instance): // …
result, err := govalidator.ValidateStruct(inMsg)
if err != nil {
return nil, grpc.Errorf(codes.InvalidArgument, "%s", err.Error())
}
// … Since I am very tied into several projects business wise, I sadly can not really help with this feature for at least half a year. If my suggestion is accepted however, I will do my best to take my share. |
@mwmahlberg so just a quick update on where the current Validators are. We've been using them in production for all of our gRPC services and they saved hundreds of boilerplate validation code. The only change we did is we moved out the validation from the proto As such, I think that Validators, in whatever shape or form, would be a great addition to Gogo. As per your proposal, we thought about doing it with struct tags but there were a couple of problems:
On a more upbeat note, you don't need to wait for Santa to try out your stuff. There's already a way to pass struct tags from |
@mwitkow I totally missed that feature. It works like a charm (except that I can't seem to get my fairly complex regex – speed is no concern for me – properly escaped 😊 ), and I was able to get rid of quite some code. However, I understand the approach. For most applications, speed is crucial Setting a standard for validation annotations seems like a great idea. I will try to dig into the code when I get some spare time. |
Wow I didn't even know there was something like govalidator. Good to know. So @mwmahlberg you found that moretags is all you need? If you really don't want to use tags and prefer comments you spend quite a bit of time to develop a new protoc-gen-gogoyournamehere binary that reads the comments in the descriptor (which is not super easy) and then transcribes these into moretags before calling all the code generation. I think using moretags is much easier :) |
@awalterschulze & @mwitkow Actually, that works pretty excellent. I have fairly complex validation running (including a domain name regex) over nested structs within 2ms. Good enough for me. If you are interested, I can set up a sample project (the project I am working on is closed source). |
I am just glad its working for you. |
You could probably split this out into a separate protoc-gen-validator binary and package that only depends on gogoprotobuf and is not a fork. |
How much work do you think it'd be to be a margeable plugin? Is it just the On Wed, 9 Mar 2016, 12:29 Walter Schulze, [email protected] wrote:
|
I just think if something can be separate it should be separate. I would rather ask is there any reason this should be part of gogoprotobuf. Its not that I don't like the work you've done here. |
I agreee, it makes sense to make it separate. It's especially useful since we're also considering building Java validators for them, so it made sense to move the I move the contents of this PR into https://github.com/mwitkow/go-proto-validators. |
Well done it looks awesome :) |
My validation language is finally ready http://katydid.github.io/ |
* work in progress*
Implementation of the validator gadget. Currently supporting regex and integer greater than/lesser than.
TODO:
#96