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

status: Fix status incompatibility introduced by #6919 and move non-regeneratable proto code into /testdata #7724

Merged
merged 9 commits into from
Oct 22, 2024
Merged
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78
github.com/envoyproxy/go-control-plane v0.13.1
github.com/golang/glog v1.2.2
github.com/golang/protobuf v1.5.4
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
golang.org/x/net v0.30.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=
github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
Expand Down
35 changes: 34 additions & 1 deletion internal/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ func (s *Status) WithDetails(details ...protoadapt.MessageV1) (*Status, error) {

// Details returns a slice of details messages attached to the status.
// If a detail cannot be decoded, the error is returned in place of the detail.
// If the detail can be decoded, the proto message returned is of the same
// type that was given to WithDetails().
func (s *Status) Details() []any {
if s == nil || s.s == nil {
return nil
Expand All @@ -160,7 +162,38 @@ func (s *Status) Details() []any {
details = append(details, err)
continue
}
details = append(details, detail)
// The call to MessageV1Of is required to unwrap the proto message if
// it implemented only the MessageV1 API. The proto message would have
// been wrapped in a V2 wrapper in Status.WithDetails. V2 messages are
// added to a global registry used by any.UnmarshalNew().
// MessageV1Of has the following behaviour:
// 1. If the given message is a wrapped MessageV1, it returns the
// unwrapped value.
// 2. If the given message already implements MessageV1, it returns it
// as is.
// 3. Else, it wraps the MessageV2 in a MessageV1 wrapper.
//
// Since the Status.WithDetails() API only accepts MessageV1, calling
// MessageV1Of ensures we return the same type that was given to
// WithDetails:
// * If the give type implemented only MessageV1, the unwrapping from
// point 1 above will restore the type.
// * If the given type implemented both MessageV1 and MessageV2, point 2
// above will ensure no wrapping is performed.
// * If the given type implemented only MessageV2 and was wrapped using
// MessageV1Of before passing to WithDetails(), it would be unwrapped
// in WithDetails by calling MessageV2Of(). Point 3 above will ensure
// that the type is wrapped in a MessageV1 wrapper again before
// returning. Note that protoc-gen-go doesn't generate code which
// implements ONLY MessageV2 at the time of writing.
//
// NOTE: Status details can also be added using the FromProto method.
// This could theoretically allow passing a Detail message that only
// implements the V2 API. In such a case the message will be wrapped in
// a MessageV1 wrapper when fetched using Details().
// Since protoc-gen-go generates only code that implements both V1 and
// V2 APIs for backward compatibility, this is not a concern.
Comment on lines +194 to +195
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this guaranteed to always be the case? (Does it matter?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

details = append(details, protoadapt.MessageV1Of(detail))
}
return details
}
Expand Down
2 changes: 2 additions & 0 deletions interop/xds/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
Expand Down
18 changes: 0 additions & 18 deletions reflection/test/go.mod

This file was deleted.

14 changes: 0 additions & 14 deletions reflection/test/go.sum

This file was deleted.

2 changes: 1 addition & 1 deletion reflection/test/serverreflection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import (
v1reflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1"
v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
pb "google.golang.org/grpc/reflection/grpc_testing"
pbv3 "google.golang.org/grpc/reflection/test/grpc_testing_not_regenerate"
pbv3 "google.golang.org/grpc/testdata/grpc_testing_not_regenerated"
)

var (
Expand Down
12 changes: 6 additions & 6 deletions scripts/regenerate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ export PATH="${GOBIN}:${PATH}"
mkdir -p "${GOBIN}"

echo "removing existing generated files..."
# grpc_testing_not_regenerate/*.pb.go is not re-generated,
# see grpc_testing_not_regenerate/README.md for details.
find . -name '*.pb.go' | grep -v 'grpc_testing_not_regenerate' | xargs rm -f || true
# grpc_testing_not_regenerated/*.pb.go is not re-generated,
# see grpc_testing_not_regenerated/README.md for details.
find . -name '*.pb.go' | grep -v 'grpc_testing_not_regenerated' | xargs rm -f || true

echo "Executing: go install google.golang.org/protobuf/cmd/protoc-gen-go..."
(cd test/tools && go install google.golang.org/protobuf/cmd/protoc-gen-go)
Expand Down Expand Up @@ -124,8 +124,8 @@ done
mkdir -p "${WORKDIR}/out/google.golang.org/grpc/internal/proto/grpc_lookup_v1"
mv "${WORKDIR}"/out/google.golang.org/grpc/lookup/grpc_lookup_v1/* "${WORKDIR}/out/google.golang.org/grpc/internal/proto/grpc_lookup_v1"

# grpc_testing_not_regenerate/*.pb.go are not re-generated,
# see grpc_testing_not_regenerate/README.md for details.
rm "${WORKDIR}"/out/google.golang.org/grpc/reflection/test/grpc_testing_not_regenerate/*.pb.go
# grpc_testing_not_regenerated/*.pb.go are not re-generated,
# see grpc_testing_not_regenerated/README.md for details.
rm "${WORKDIR}"/out/google.golang.org/grpc/testdata/grpc_testing_not_regenerated/*.pb.go

cp -R "${WORKDIR}"/out/google.golang.org/grpc/* .
10 changes: 5 additions & 5 deletions scripts/vet.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ git grep 'func [A-Z]' -- "*_test.go" | not grep -v 'func Test\|Benchmark\|Exampl
git grep -l 'time.After(' -- "*.go" | not grep -v '_test.go\|test_utils\|testutils'

# - Do not use "interface{}"; use "any" instead.
git grep -l 'interface{}' -- "*.go" 2>&1 | not grep -v '\.pb\.go\|protoc-gen-go-grpc\|grpc_testing_not_regenerate'
git grep -l 'interface{}' -- "*.go" 2>&1 | not grep -v '\.pb\.go\|protoc-gen-go-grpc\|grpc_testing_not_regenerated'

# - Do not call grpclog directly. Use grpclog.Component instead.
git grep -l -e 'grpclog.I' --or -e 'grpclog.W' --or -e 'grpclog.E' --or -e 'grpclog.F' --or -e 'grpclog.V' -- "*.go" | not grep -v '^grpclog/component.go\|^internal/grpctest/tlogger_test.go\|^internal/grpclog/prefix_logger.go'

# - Ensure that the deprecated protobuf dependency is not used.
not git grep "\"github.com/golang/protobuf/*" -- "*.go" ':(exclude)reflection/test/grpc_testing_not_regenerate/*'
not git grep "\"github.com/golang/protobuf/*" -- "*.go" ':(exclude)testdata/grpc_testing_not_regenerated/*'

# - Ensure all usages of grpc_testing package are renamed when importing.
not git grep "\(import \|^\s*\)\"google.golang.org/grpc/interop/grpc_testing" -- "*.go"
Expand Down Expand Up @@ -112,7 +112,7 @@ for MOD_FILE in $(find . -name 'go.mod'); do
noret_grep -v "(ST1000)" "${SC_OUT}" | noret_grep -v "(SA1019)" | noret_grep -v "(ST1003)" | noret_grep -v "(ST1019)\|\(other import of\)" | not grep -v "(SA4000)"

# Exclude underscore checks for generated code.
noret_grep "(ST1003)" "${SC_OUT}" | not grep -v '\(.pb.go:\)\|\(code_string_test.go:\)\|\(grpc_testing_not_regenerate\)'
noret_grep "(ST1003)" "${SC_OUT}" | not grep -v '\(.pb.go:\)\|\(code_string_test.go:\)\|\(grpc_testing_not_regenerated\)'

# Error for duplicate imports not including grpc protos.
noret_grep "(ST1019)\|\(other import of\)" "${SC_OUT}" | not grep -Fv 'XXXXX PleaseIgnoreUnused
Expand Down Expand Up @@ -149,7 +149,7 @@ XXXXX PleaseIgnoreUnused'
XXXXX Protobuf related deprecation errors:
"github.com/golang/protobuf
.pb.go:
grpc_testing_not_regenerate
grpc_testing_not_regenerated
: ptypes.
proto.RegisterType
XXXXX gRPC internal usage deprecation errors:
Expand Down Expand Up @@ -191,7 +191,7 @@ done
# Error for violation of enabled lint rules in config excluding generated code.
revive \
-set_exit_status=1 \
-exclude "reflection/test/grpc_testing_not_regenerate/" \
-exclude "testdata/grpc_testing_not_regenerated/" \
-exclude "**/*.pb.go" \
-formatter plain \
-config "$(dirname "$0")/revive.toml" \
Expand Down
2 changes: 2 additions & 0 deletions security/advancedtls/examples/go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
Expand Down
2 changes: 2 additions & 0 deletions security/advancedtls/go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
Expand Down
2 changes: 2 additions & 0 deletions stats/opencensus/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
Expand Down
2 changes: 2 additions & 0 deletions stats/opentelemetry/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
Expand Down
56 changes: 56 additions & 0 deletions status/status_ext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package status_test
import (
"context"
"errors"
"reflect"
"strings"
"testing"
"time"
Expand All @@ -35,8 +36,10 @@ import (
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/protoadapt"
"google.golang.org/protobuf/testing/protocmp"

testpb "google.golang.org/grpc/interop/grpc_testing"
tpb "google.golang.org/grpc/testdata/grpc_testing_not_regenerated"
)

const defaultTestTimeout = 10 * time.Second
Expand Down Expand Up @@ -203,3 +206,56 @@ func (s) TestStatusDetails(t *testing.T) {
})
}
}

// TestStatus_ErrorDetailsMessageV1 verifies backward compatibility of the
// status.Details() method when using protobuf code generated with only the
// MessageV1 API implementation.
func (s) TestStatus_ErrorDetailsMessageV1(t *testing.T) {
details := []protoadapt.MessageV1{
&tpb.SimpleMessage{Data: "abc"},
}
s, err := status.New(codes.Aborted, "").WithDetails(details...)
if err != nil {
t.Fatalf("(%v).WithDetails(%+v) failed: %v", s, details, err)
}
gotDetails := s.Details()
for i, msg := range gotDetails {
if got, want := reflect.TypeOf(msg), reflect.TypeOf(details[i]); got != want {
t.Errorf("reflect.Typeof(%v) = %v, want = %v", msg, got, want)
}
if _, ok := msg.(protoadapt.MessageV1); !ok {
t.Errorf("(%v).Details() returned message that doesn't implement protoadapt.MessageV1: %v", s, msg)
}
if diff := cmp.Diff(msg, details[i], protocmp.Transform()); diff != "" {
t.Errorf("(%v).Details got unexpected output, diff (-got +want):\n%s", s, diff)
}
}
}

// TestStatus_ErrorDetailsMessageV1AndV2 verifies that status.Details() method
// returns the same message types when using protobuf code generated with both the
// MessageV1 and MessageV2 API implementations.
func (s) TestStatus_ErrorDetailsMessageV1AndV2(t *testing.T) {
details := []protoadapt.MessageV1{
&testpb.Empty{},
}
s, err := status.New(codes.Aborted, "").WithDetails(details...)
if err != nil {
t.Fatalf("(%v).WithDetails(%+v) failed: %v", s, details, err)
}
gotDetails := s.Details()
for i, msg := range gotDetails {
if got, want := reflect.TypeOf(msg), reflect.TypeOf(details[i]); got != want {
t.Errorf("reflect.Typeof(%v) = %v, want = %v", msg, got, want)
}
if _, ok := msg.(protoadapt.MessageV1); !ok {
t.Errorf("(%v).Details() returned message that doesn't implement protoadapt.MessageV1: %v", s, msg)
}
if _, ok := msg.(protoadapt.MessageV2); !ok {
t.Errorf("(%v).Details() returned message that doesn't implement protoadapt.MessageV2: %v", s, msg)
}
if diff := cmp.Diff(msg, details[i], protocmp.Transform()); diff != "" {
t.Errorf("(%v).Details got unexpected output, diff (-got +want):\n%s", s, diff)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ with `"context"`.

`dynamic.go` was generated with a newer protoc and manually edited to remove
everything except the descriptor bytes var, which is renamed and exported.

`simple_message_v1.go` was generated using protoc-gen-go v1.3.5 which doesn't
support the MesssageV2 API. As a result the generated code implements only the
old MessageV1 API.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*
*/

package grpc_testing_not_regenerate
package grpc_testing_not_regenerated

// FileDynamicProtoRawDesc is the descriptor for dynamic.proto, see README.md.
var FileDynamicProtoRawDesc = []byte{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

syntax = "proto3";

option go_package = "google.golang.org/grpc/reflection/test/grpc_testing_not_regenerate";

package grpc.testing;

option go_package = "google.golang.org/grpc/testdata/grpc_testing_not_regenerated";

message DynamicRes {}

message DynamicReq {}
Expand Down
27 changes: 27 additions & 0 deletions testdata/grpc_testing_not_regenerated/simple.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2024 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

syntax = "proto3";

package grpc.testdata.grpc_testing_not_regenerated;

option go_package = "google.golang.org/grpc/testdata/grpc_testing_not_regenerated";

// SimpleMessage is used to hold string data.
message SimpleMessage {
string data = 1;
}
Loading
Loading