status: Fix status incompatibility introduced by #6919 and move non-regeneratable proto code into /testdata#7724
Conversation
c313346 to
3b088a0
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #7724 +/- ##
==========================================
+ Coverage 79.70% 80.25% +0.54%
==========================================
Files 365 367 +2
Lines 36383 36622 +239
==========================================
+ Hits 29000 29390 +390
+ Misses 6183 6040 -143
+ Partials 1200 1192 -8
|
| } | ||
|
|
||
| if diff := cmp.Diff(details, gotDetails, protocmp.Transform()); diff != "" { | ||
| t.Errorf("(%v).Details got unexpected output, diff (-got +want):\n%s", s, diff) |
There was a problem hiding this comment.
The order in the output, (-got +want), needs to be swapped I guess based on the order of parameters passed to cmp.Diff.
| details := []protoadapt.MessageV1{ | ||
| &tpb.SimpleMessage{ | ||
| Data: "abc", | ||
| }, | ||
| &testpb.Empty{}, | ||
| } |
There was a problem hiding this comment.
Minor nit (optional)
I feel this is more readable and compact:
details := []protoadapt.MessageV1{
&tpb.SimpleMessage{Data: "abc"},
&testpb.Empty{},
}There was a problem hiding this comment.
Changed as suggested.
| @@ -0,0 +1,27 @@ | |||
| /* | |||
| * Copyright 2022 gRPC authors. | |||
| // Since protoc-gen-go generates only code that implements both V1 and | ||
| // V2 APIs for backward compatibility, this is not a concern. |
There was a problem hiding this comment.
Is this guaranteed to always be the case? (Does it matter?)
There was a problem hiding this comment.
Is this guaranteed to always be the case?
I don't think so. The V1 API is deprecated and is only present for backward compatibility. There is no guarantee that protoc-gen-go will always support it.
Does it matter?
protoadapt.MessageV1Of will return a wrapped message which implements the V1 API when the argument doesn't implement it already. Callers will need to unwrap it using the protoadapt.MessageV2Of to get the inner type.
This is why I updated the doc comment to say the following:
If the detail can be decoded, the proto message returned is of the same type that was given to WithDetails().
status.WithDetails accepts only V1 messages. To pass it a V2 message, it will need to be wrapped and status.Details() will return the same wrapped type.
| replace google.golang.org/grpc => ../../ | ||
|
|
||
| require ( | ||
| github.com/golang/protobuf v1.5.4 |
There was a problem hiding this comment.
IIRC, the only reason this file was here is to hide this module dependency, since it's deprecated. Let's just delete this file now. I think we're going to have to accept a huge module dependency list, which is why I created #7690 - to make sure our actual production code dependencies can be tracked.
There was a problem hiding this comment.
Removed the go.mod and go.sum files from reflection/test/.
| option go_package = "google.golang.org/grpc/testdata/grpc_testing_not_regenerate"; | ||
|
|
||
| // SimpleMessage is used to hold string data. | ||
| message SimpleMessage { |
There was a problem hiding this comment.
I feel it is better to name the test message as MessageV1Only, and give a short comments describing why it must not be regenerated.
There was a problem hiding this comment.
I feel like "implementing the V1 API" is a property of the generated code and not the proto itself. There is a README.md describing the use of each generated file and how it was generated.
| gotDetails = append(gotDetails, msg) | ||
| } | ||
|
|
||
| if diff := cmp.Diff(details, gotDetails, protocmp.Transform()); diff != "" { |
There was a problem hiding this comment.
I just have glance on cmp.Diff, look like it is used to convert proto.Message into map-like structure, then perform a recursive "value-equal" check.
I think such examination does not satisfy "the proto message returned by Details() is of the same type that was given to WithDetails()". A reflect.Type check is preferred in such situation.
There was a problem hiding this comment.
You're right, added a type comparison using reflect.TypeOf.
| func (s) TestStatus_ErrorDetailsMessageV1(t *testing.T) { | ||
| details := []protoadapt.MessageV1{ | ||
| &tpb.SimpleMessage{Data: "abc"}, | ||
| &testpb.Empty{}, |
There was a problem hiding this comment.
According to the test comments, should testpb.Empty be removed ?
There was a problem hiding this comment.
Yes, removed. I wanted to keep a test case for ensuring v1 + v2 messages are also handled correctly, added a new test function for that later.
| option go_package = "google.golang.org/grpc/testdata/grpc_testing_not_regenerate"; | ||
|
|
||
| // SimpleMessage is used to hold string data. | ||
| message SimpleMessage { |
dfawley
left a comment
There was a problem hiding this comment.
Super nitpicky, but maybe this is easy to fix?
$ mv testdata/grpc_testing_not_regenerate testdata/grpc_testing_not_regenerated
$ grep -rl not_regenerate | xargs sed -i 's/grpc_testing_not_regenerate/grpc_testing_not_regenerated/g'
Maybe if it's that easy, change it? The awkward use of english always bothered me here. :)
"do_not_regenerate" or "dont_regenerate" would also be fine.
Renamed the directory. It required re-generating the message V1 only proto as it started panicking during registration: |
cc49daf to
6009694
Compare
…on-regeneratable proto code into /testdata (grpc#7724)
…on-regeneratable proto code into /testdata (grpc#7724)
…on-regeneratable proto code into /testdata (grpc#7724)
Fixes: #7679
Problem
#6919 migrated usages of
github.com/golang/protobuftogoogle.golang.org/protobuf/protowithinstatuspackage. Prior to this, status.Details() calledptypes.UnmarshalAnywhich calledproto.MessageV1(mt.New().Interface())which calledprotoimpl.X.ProtoMessageV1Of(m)so the returned type always implementedprotoadapt.MessageV1and was always the same type given to status.WithDetails(). After the change,Status.Details()usedanpb.Any.UnmarshallNew()which returns the vanilla type used while creating theanypb.Anywhich is only guaranteed to implement theMessageV2API.Effect
Users of code generated from
protoc-gen-go< v1.4 (launched in 2020) would get a wrapped MessageV2 when callingStatus.Details()even though they would have provided a type that only implementedMessageV1toStatus.WithDetails().Fix
This PR brings back the call to
protoimpl.X.ProtoMessageV1Of(m)by callingprotoadapt.MessageV1Ofbefore returning the Detail messages. A test is also added to catch regressions. Since the test uses generated code fromprotoc-gen-gov1.3, a dependency ongithub.com/golang/protobufis re-introduced ingo.mod.Additional Changes
This PR also moves the generated code that is used for testing and must not be re-generated from the
reflections/testmodule into a common directory under the parentgrpcmodule.RELEASE NOTES: