From 44bc953a426874e7c4cc49c91af0903b83f90477 Mon Sep 17 00:00:00 2001 From: Brenna N Epp Date: Mon, 18 Oct 2021 16:54:09 -0700 Subject: [PATCH] test(storage): init retry conformance test scaffolding (#4711) Co-authored-by: Chris Cotter --- .../test/conformance/retry_tests.json | 45 + storage/internal/test/conformance/test.pb.go | 1542 ++++++++++++----- storage/internal/test/conformance/test.proto | 119 ++ storage/retry_conformance_test.go | 318 ++++ 4 files changed, 1634 insertions(+), 390 deletions(-) create mode 100644 storage/internal/test/conformance/retry_tests.json create mode 100644 storage/retry_conformance_test.go diff --git a/storage/internal/test/conformance/retry_tests.json b/storage/internal/test/conformance/retry_tests.json new file mode 100644 index 00000000000..0fe11477591 --- /dev/null +++ b/storage/internal/test/conformance/retry_tests.json @@ -0,0 +1,45 @@ +{ + "retryTests": [ + { + "id": 1, + "description": "always_idempotent", + "cases": [ + { + "instructions": ["return-503", "return-503"] + }, + { + "instructions": ["return-reset-connection", "return-reset-connection"] + }, + { + "instructions": ["return-reset-connection", "return-503"] + } + ], + "methods": [ + {"name": "storage.bucket_acl.get", "resources": ["BUCKET"]}, + {"name": "storage.bucket_acl.list", "resources": ["BUCKET"]}, + {"name": "storage.buckets.delete", "resources": ["BUCKET"]}, + {"name": "storage.buckets.get", "resources": ["BUCKET"]}, + {"name": "storage.buckets.getIamPolicy", "resources": ["BUCKET"]}, + {"name": "storage.buckets.insert", "resources": []}, + {"name": "storage.buckets.list", "resources": ["BUCKET"]}, + {"name": "storage.buckets.lockRetentionPolicy", "resources": ["BUCKET"]}, + {"name": "storage.buckets.testIamPermissions", "resources": ["BUCKET"]}, + {"name": "storage.default_object_acl.get", "resources": ["BUCKET"]}, + {"name": "storage.default_object_acl.list", "resources": ["BUCKET"]}, + {"name": "storage.hmacKey.delete", "resources": ["HMAC_KEY"]}, + {"name": "storage.hmacKey.get", "resources": ["HMAC_KEY"]}, + {"name": "storage.hmacKey.list", "resources": ["HMAC_KEY"]}, + {"name": "storage.notifications.delete", "resources": ["BUCKET", "NOTIFICATION"]}, + {"name": "storage.notifications.get", "resources": ["BUCKET", "NOTIFICATION"]}, + {"name": "storage.notifications.list", "resources": ["BUCKET", "NOTIFICATION"]}, + {"name": "storage.object_acl.get", "resources": ["BUCKET", "OBJECT"]}, + {"name": "storage.object_acl.list", "resources": ["BUCKET", "OBJECT"]}, + {"name": "storage.objects.get", "resources": ["BUCKET", "OBJECT"]}, + {"name": "storage.objects.list", "resources": ["BUCKET", "OBJECT"]}, + {"name": "storage.serviceaccount.get", "resources": []} + ], + "preconditionProvided": false, + "expectSuccess": true + } + ] +} diff --git a/storage/internal/test/conformance/test.pb.go b/storage/internal/test/conformance/test.pb.go index df7d64e4c94..2ff5a7e9abb 100644 --- a/storage/internal/test/conformance/test.pb.go +++ b/storage/internal/test/conformance/test.pb.go @@ -1,26 +1,40 @@ +// Copyright 2019, Google LLC +// +// 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 +// +// https://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 + // Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.17.3 // source: test.proto -package google_cloud_conformance_storage_v1 +package v1 import ( - fmt "fmt" - math "math" + reflect "reflect" + sync "sync" - proto "github.com/golang/protobuf/proto" - timestamp "github.com/golang/protobuf/ptypes/timestamp" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +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 UrlStyle int32 @@ -30,597 +44,1345 @@ const ( UrlStyle_BUCKET_BOUND_HOSTNAME UrlStyle = 2 ) -var UrlStyle_name = map[int32]string{ - 0: "PATH_STYLE", - 1: "VIRTUAL_HOSTED_STYLE", - 2: "BUCKET_BOUND_HOSTNAME", -} +// Enum value maps for UrlStyle. +var ( + UrlStyle_name = map[int32]string{ + 0: "PATH_STYLE", + 1: "VIRTUAL_HOSTED_STYLE", + 2: "BUCKET_BOUND_HOSTNAME", + } + UrlStyle_value = map[string]int32{ + "PATH_STYLE": 0, + "VIRTUAL_HOSTED_STYLE": 1, + "BUCKET_BOUND_HOSTNAME": 2, + } +) -var UrlStyle_value = map[string]int32{ - "PATH_STYLE": 0, - "VIRTUAL_HOSTED_STYLE": 1, - "BUCKET_BOUND_HOSTNAME": 2, +func (x UrlStyle) Enum() *UrlStyle { + p := new(UrlStyle) + *p = x + return p } func (x UrlStyle) String() string { - return proto.EnumName(UrlStyle_name, int32(x)) + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (UrlStyle) Descriptor() protoreflect.EnumDescriptor { + return file_test_proto_enumTypes[0].Descriptor() +} + +func (UrlStyle) Type() protoreflect.EnumType { + return &file_test_proto_enumTypes[0] } +func (x UrlStyle) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use UrlStyle.Descriptor instead. func (UrlStyle) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{0} + return file_test_proto_rawDescGZIP(), []int{0} } -type TestFile struct { - SigningV4Tests []*SigningV4Test `protobuf:"bytes,1,rep,name=signing_v4_tests,json=signingV4Tests,proto3" json:"signing_v4_tests,omitempty"` - PostPolicyV4Tests []*PostPolicyV4Test `protobuf:"bytes,2,rep,name=post_policy_v4_tests,json=postPolicyV4Tests,proto3" json:"post_policy_v4_tests,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +// Test resources that are necessary for a method call. For example, +// storage.objects.get would require BUCKET and OBJECT. +type Resource int32 + +const ( + Resource_BUCKET Resource = 0 + Resource_OBJECT Resource = 1 + Resource_NOTIFICATION Resource = 2 + Resource_HMAC_KEY Resource = 3 +) + +// Enum value maps for Resource. +var ( + Resource_name = map[int32]string{ + 0: "BUCKET", + 1: "OBJECT", + 2: "NOTIFICATION", + 3: "HMAC_KEY", + } + Resource_value = map[string]int32{ + "BUCKET": 0, + "OBJECT": 1, + "NOTIFICATION": 2, + "HMAC_KEY": 3, + } +) + +func (x Resource) Enum() *Resource { + p := new(Resource) + *p = x + return p } -func (m *TestFile) Reset() { *m = TestFile{} } -func (m *TestFile) String() string { return proto.CompactTextString(m) } -func (*TestFile) ProtoMessage() {} -func (*TestFile) Descriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{0} +func (x Resource) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } -func (m *TestFile) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_TestFile.Unmarshal(m, b) +func (Resource) Descriptor() protoreflect.EnumDescriptor { + return file_test_proto_enumTypes[1].Descriptor() } -func (m *TestFile) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_TestFile.Marshal(b, m, deterministic) + +func (Resource) Type() protoreflect.EnumType { + return &file_test_proto_enumTypes[1] +} + +func (x Resource) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) } -func (m *TestFile) XXX_Merge(src proto.Message) { - xxx_messageInfo_TestFile.Merge(m, src) + +// Deprecated: Use Resource.Descriptor instead. +func (Resource) EnumDescriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{1} +} + +type TestFile struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SigningV4Tests []*SigningV4Test `protobuf:"bytes,1,rep,name=signing_v4_tests,json=signingV4Tests,proto3" json:"signing_v4_tests,omitempty"` + PostPolicyV4Tests []*PostPolicyV4Test `protobuf:"bytes,2,rep,name=post_policy_v4_tests,json=postPolicyV4Tests,proto3" json:"post_policy_v4_tests,omitempty"` + RetryTests []*RetryTest `protobuf:"bytes,3,rep,name=retry_tests,json=retryTests,proto3" json:"retry_tests,omitempty"` } -func (m *TestFile) XXX_Size() int { - return xxx_messageInfo_TestFile.Size(m) + +func (x *TestFile) Reset() { + *x = TestFile{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *TestFile) XXX_DiscardUnknown() { - xxx_messageInfo_TestFile.DiscardUnknown(m) + +func (x *TestFile) String() string { + return protoimpl.X.MessageStringOf(x) } -var xxx_messageInfo_TestFile proto.InternalMessageInfo +func (*TestFile) ProtoMessage() {} -func (m *TestFile) GetSigningV4Tests() []*SigningV4Test { - if m != nil { - return m.SigningV4Tests +func (x *TestFile) ProtoReflect() protoreflect.Message { + mi := &file_test_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 nil + return mi.MessageOf(x) } -func (m *TestFile) GetPostPolicyV4Tests() []*PostPolicyV4Test { - if m != nil { - return m.PostPolicyV4Tests +// Deprecated: Use TestFile.ProtoReflect.Descriptor instead. +func (*TestFile) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{0} +} + +func (x *TestFile) GetSigningV4Tests() []*SigningV4Test { + if x != nil { + return x.SigningV4Tests } return nil } -type SigningV4Test struct { - FileName string `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - Bucket string `protobuf:"bytes,3,opt,name=bucket,proto3" json:"bucket,omitempty"` - Object string `protobuf:"bytes,4,opt,name=object,proto3" json:"object,omitempty"` - Method string `protobuf:"bytes,5,opt,name=method,proto3" json:"method,omitempty"` - Expiration int64 `protobuf:"varint,6,opt,name=expiration,proto3" json:"expiration,omitempty"` - Timestamp *timestamp.Timestamp `protobuf:"bytes,7,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - ExpectedUrl string `protobuf:"bytes,8,opt,name=expectedUrl,proto3" json:"expectedUrl,omitempty"` - Headers map[string]string `protobuf:"bytes,9,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - QueryParameters map[string]string `protobuf:"bytes,10,rep,name=query_parameters,json=queryParameters,proto3" json:"query_parameters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Scheme string `protobuf:"bytes,11,opt,name=scheme,proto3" json:"scheme,omitempty"` - UrlStyle UrlStyle `protobuf:"varint,12,opt,name=urlStyle,proto3,enum=google.cloud.conformance.storage.v1.UrlStyle" json:"urlStyle,omitempty"` - BucketBoundHostname string `protobuf:"bytes,13,opt,name=bucketBoundHostname,proto3" json:"bucketBoundHostname,omitempty"` - ExpectedCanonicalRequest string `protobuf:"bytes,14,opt,name=expectedCanonicalRequest,proto3" json:"expectedCanonicalRequest,omitempty"` - ExpectedStringToSign string `protobuf:"bytes,15,opt,name=expectedStringToSign,proto3" json:"expectedStringToSign,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *SigningV4Test) Reset() { *m = SigningV4Test{} } -func (m *SigningV4Test) String() string { return proto.CompactTextString(m) } -func (*SigningV4Test) ProtoMessage() {} -func (*SigningV4Test) Descriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{1} +func (x *TestFile) GetPostPolicyV4Tests() []*PostPolicyV4Test { + if x != nil { + return x.PostPolicyV4Tests + } + return nil } -func (m *SigningV4Test) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SigningV4Test.Unmarshal(m, b) -} -func (m *SigningV4Test) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SigningV4Test.Marshal(b, m, deterministic) +func (x *TestFile) GetRetryTests() []*RetryTest { + if x != nil { + return x.RetryTests + } + return nil } -func (m *SigningV4Test) XXX_Merge(src proto.Message) { - xxx_messageInfo_SigningV4Test.Merge(m, src) + +type SigningV4Test struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FileName string `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Bucket string `protobuf:"bytes,3,opt,name=bucket,proto3" json:"bucket,omitempty"` + Object string `protobuf:"bytes,4,opt,name=object,proto3" json:"object,omitempty"` + Method string `protobuf:"bytes,5,opt,name=method,proto3" json:"method,omitempty"` + Expiration int64 `protobuf:"varint,6,opt,name=expiration,proto3" json:"expiration,omitempty"` + Timestamp *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + ExpectedUrl string `protobuf:"bytes,8,opt,name=expectedUrl,proto3" json:"expectedUrl,omitempty"` + Headers map[string]string `protobuf:"bytes,9,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + QueryParameters map[string]string `protobuf:"bytes,10,rep,name=query_parameters,json=queryParameters,proto3" json:"query_parameters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Scheme string `protobuf:"bytes,11,opt,name=scheme,proto3" json:"scheme,omitempty"` + UrlStyle UrlStyle `protobuf:"varint,12,opt,name=urlStyle,proto3,enum=google.cloud.conformance.storage.v1.UrlStyle" json:"urlStyle,omitempty"` + BucketBoundHostname string `protobuf:"bytes,13,opt,name=bucketBoundHostname,proto3" json:"bucketBoundHostname,omitempty"` + ExpectedCanonicalRequest string `protobuf:"bytes,14,opt,name=expectedCanonicalRequest,proto3" json:"expectedCanonicalRequest,omitempty"` + ExpectedStringToSign string `protobuf:"bytes,15,opt,name=expectedStringToSign,proto3" json:"expectedStringToSign,omitempty"` +} + +func (x *SigningV4Test) Reset() { + *x = SigningV4Test{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *SigningV4Test) XXX_Size() int { - return xxx_messageInfo_SigningV4Test.Size(m) + +func (x *SigningV4Test) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *SigningV4Test) XXX_DiscardUnknown() { - xxx_messageInfo_SigningV4Test.DiscardUnknown(m) + +func (*SigningV4Test) ProtoMessage() {} + +func (x *SigningV4Test) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[1] + 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) } -var xxx_messageInfo_SigningV4Test proto.InternalMessageInfo +// Deprecated: Use SigningV4Test.ProtoReflect.Descriptor instead. +func (*SigningV4Test) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{1} +} -func (m *SigningV4Test) GetFileName() string { - if m != nil { - return m.FileName +func (x *SigningV4Test) GetFileName() string { + if x != nil { + return x.FileName } return "" } -func (m *SigningV4Test) GetDescription() string { - if m != nil { - return m.Description +func (x *SigningV4Test) GetDescription() string { + if x != nil { + return x.Description } return "" } -func (m *SigningV4Test) GetBucket() string { - if m != nil { - return m.Bucket +func (x *SigningV4Test) GetBucket() string { + if x != nil { + return x.Bucket } return "" } -func (m *SigningV4Test) GetObject() string { - if m != nil { - return m.Object +func (x *SigningV4Test) GetObject() string { + if x != nil { + return x.Object } return "" } -func (m *SigningV4Test) GetMethod() string { - if m != nil { - return m.Method +func (x *SigningV4Test) GetMethod() string { + if x != nil { + return x.Method } return "" } -func (m *SigningV4Test) GetExpiration() int64 { - if m != nil { - return m.Expiration +func (x *SigningV4Test) GetExpiration() int64 { + if x != nil { + return x.Expiration } return 0 } -func (m *SigningV4Test) GetTimestamp() *timestamp.Timestamp { - if m != nil { - return m.Timestamp +func (x *SigningV4Test) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp } return nil } -func (m *SigningV4Test) GetExpectedUrl() string { - if m != nil { - return m.ExpectedUrl +func (x *SigningV4Test) GetExpectedUrl() string { + if x != nil { + return x.ExpectedUrl } return "" } -func (m *SigningV4Test) GetHeaders() map[string]string { - if m != nil { - return m.Headers +func (x *SigningV4Test) GetHeaders() map[string]string { + if x != nil { + return x.Headers } return nil } -func (m *SigningV4Test) GetQueryParameters() map[string]string { - if m != nil { - return m.QueryParameters +func (x *SigningV4Test) GetQueryParameters() map[string]string { + if x != nil { + return x.QueryParameters } return nil } -func (m *SigningV4Test) GetScheme() string { - if m != nil { - return m.Scheme +func (x *SigningV4Test) GetScheme() string { + if x != nil { + return x.Scheme } return "" } -func (m *SigningV4Test) GetUrlStyle() UrlStyle { - if m != nil { - return m.UrlStyle +func (x *SigningV4Test) GetUrlStyle() UrlStyle { + if x != nil { + return x.UrlStyle } return UrlStyle_PATH_STYLE } -func (m *SigningV4Test) GetBucketBoundHostname() string { - if m != nil { - return m.BucketBoundHostname +func (x *SigningV4Test) GetBucketBoundHostname() string { + if x != nil { + return x.BucketBoundHostname } return "" } -func (m *SigningV4Test) GetExpectedCanonicalRequest() string { - if m != nil { - return m.ExpectedCanonicalRequest +func (x *SigningV4Test) GetExpectedCanonicalRequest() string { + if x != nil { + return x.ExpectedCanonicalRequest } return "" } -func (m *SigningV4Test) GetExpectedStringToSign() string { - if m != nil { - return m.ExpectedStringToSign +func (x *SigningV4Test) GetExpectedStringToSign() string { + if x != nil { + return x.ExpectedStringToSign } return "" } type ConditionalMatches struct { - Expression []string `protobuf:"bytes,1,rep,name=expression,proto3" json:"expression,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *ConditionalMatches) Reset() { *m = ConditionalMatches{} } -func (m *ConditionalMatches) String() string { return proto.CompactTextString(m) } -func (*ConditionalMatches) ProtoMessage() {} -func (*ConditionalMatches) Descriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{2} + Expression []string `protobuf:"bytes,1,rep,name=expression,proto3" json:"expression,omitempty"` } -func (m *ConditionalMatches) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ConditionalMatches.Unmarshal(m, b) -} -func (m *ConditionalMatches) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ConditionalMatches.Marshal(b, m, deterministic) -} -func (m *ConditionalMatches) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConditionalMatches.Merge(m, src) +func (x *ConditionalMatches) Reset() { + *x = ConditionalMatches{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *ConditionalMatches) XXX_Size() int { - return xxx_messageInfo_ConditionalMatches.Size(m) + +func (x *ConditionalMatches) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *ConditionalMatches) XXX_DiscardUnknown() { - xxx_messageInfo_ConditionalMatches.DiscardUnknown(m) + +func (*ConditionalMatches) ProtoMessage() {} + +func (x *ConditionalMatches) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[2] + 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) } -var xxx_messageInfo_ConditionalMatches proto.InternalMessageInfo +// Deprecated: Use ConditionalMatches.ProtoReflect.Descriptor instead. +func (*ConditionalMatches) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{2} +} -func (m *ConditionalMatches) GetExpression() []string { - if m != nil { - return m.Expression +func (x *ConditionalMatches) GetExpression() []string { + if x != nil { + return x.Expression } return nil } type PolicyConditions struct { - ContentLengthRange []int32 `protobuf:"varint,1,rep,packed,name=contentLengthRange,proto3" json:"contentLengthRange,omitempty"` - StartsWith []string `protobuf:"bytes,2,rep,name=startsWith,proto3" json:"startsWith,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *PolicyConditions) Reset() { *m = PolicyConditions{} } -func (m *PolicyConditions) String() string { return proto.CompactTextString(m) } -func (*PolicyConditions) ProtoMessage() {} -func (*PolicyConditions) Descriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{3} + ContentLengthRange []int32 `protobuf:"varint,1,rep,packed,name=contentLengthRange,proto3" json:"contentLengthRange,omitempty"` + StartsWith []string `protobuf:"bytes,2,rep,name=startsWith,proto3" json:"startsWith,omitempty"` } -func (m *PolicyConditions) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PolicyConditions.Unmarshal(m, b) -} -func (m *PolicyConditions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PolicyConditions.Marshal(b, m, deterministic) -} -func (m *PolicyConditions) XXX_Merge(src proto.Message) { - xxx_messageInfo_PolicyConditions.Merge(m, src) +func (x *PolicyConditions) Reset() { + *x = PolicyConditions{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *PolicyConditions) XXX_Size() int { - return xxx_messageInfo_PolicyConditions.Size(m) + +func (x *PolicyConditions) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *PolicyConditions) XXX_DiscardUnknown() { - xxx_messageInfo_PolicyConditions.DiscardUnknown(m) + +func (*PolicyConditions) ProtoMessage() {} + +func (x *PolicyConditions) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[3] + 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) } -var xxx_messageInfo_PolicyConditions proto.InternalMessageInfo +// Deprecated: Use PolicyConditions.ProtoReflect.Descriptor instead. +func (*PolicyConditions) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{3} +} -func (m *PolicyConditions) GetContentLengthRange() []int32 { - if m != nil { - return m.ContentLengthRange +func (x *PolicyConditions) GetContentLengthRange() []int32 { + if x != nil { + return x.ContentLengthRange } return nil } -func (m *PolicyConditions) GetStartsWith() []string { - if m != nil { - return m.StartsWith +func (x *PolicyConditions) GetStartsWith() []string { + if x != nil { + return x.StartsWith } return nil } type PolicyInput struct { - Scheme string `protobuf:"bytes,1,opt,name=scheme,proto3" json:"scheme,omitempty"` - UrlStyle UrlStyle `protobuf:"varint,2,opt,name=urlStyle,proto3,enum=google.cloud.conformance.storage.v1.UrlStyle" json:"urlStyle,omitempty"` - BucketBoundHostname string `protobuf:"bytes,3,opt,name=bucketBoundHostname,proto3" json:"bucketBoundHostname,omitempty"` - Bucket string `protobuf:"bytes,4,opt,name=bucket,proto3" json:"bucket,omitempty"` - Object string `protobuf:"bytes,5,opt,name=object,proto3" json:"object,omitempty"` - Expiration int32 `protobuf:"varint,6,opt,name=expiration,proto3" json:"expiration,omitempty"` - Timestamp *timestamp.Timestamp `protobuf:"bytes,7,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Fields map[string]string `protobuf:"bytes,8,rep,name=fields,proto3" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Conditions *PolicyConditions `protobuf:"bytes,9,opt,name=conditions,proto3" json:"conditions,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PolicyInput) Reset() { *m = PolicyInput{} } -func (m *PolicyInput) String() string { return proto.CompactTextString(m) } -func (*PolicyInput) ProtoMessage() {} -func (*PolicyInput) Descriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{4} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // http or https + Scheme string `protobuf:"bytes,1,opt,name=scheme,proto3" json:"scheme,omitempty"` + UrlStyle UrlStyle `protobuf:"varint,2,opt,name=urlStyle,proto3,enum=google.cloud.conformance.storage.v1.UrlStyle" json:"urlStyle,omitempty"` + BucketBoundHostname string `protobuf:"bytes,3,opt,name=bucketBoundHostname,proto3" json:"bucketBoundHostname,omitempty"` + Bucket string `protobuf:"bytes,4,opt,name=bucket,proto3" json:"bucket,omitempty"` + Object string `protobuf:"bytes,5,opt,name=object,proto3" json:"object,omitempty"` + Expiration int32 `protobuf:"varint,6,opt,name=expiration,proto3" json:"expiration,omitempty"` + Timestamp *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // + //fields with strict equivalence which are added into + //PolicyOutput.expectedDecodedPolicy to generate the + //signature. + //Expectations + //E.1: Order them in lexigraphical order so it's the + //signature can be verified across different language + //implementations. + Fields map[string]string `protobuf:"bytes,8,rep,name=fields,proto3" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Conditions *PolicyConditions `protobuf:"bytes,9,opt,name=conditions,proto3" json:"conditions,omitempty"` +} + +func (x *PolicyInput) Reset() { + *x = PolicyInput{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *PolicyInput) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PolicyInput.Unmarshal(m, b) -} -func (m *PolicyInput) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PolicyInput.Marshal(b, m, deterministic) -} -func (m *PolicyInput) XXX_Merge(src proto.Message) { - xxx_messageInfo_PolicyInput.Merge(m, src) +func (x *PolicyInput) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *PolicyInput) XXX_Size() int { - return xxx_messageInfo_PolicyInput.Size(m) -} -func (m *PolicyInput) XXX_DiscardUnknown() { - xxx_messageInfo_PolicyInput.DiscardUnknown(m) + +func (*PolicyInput) ProtoMessage() {} + +func (x *PolicyInput) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[4] + 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) } -var xxx_messageInfo_PolicyInput proto.InternalMessageInfo +// Deprecated: Use PolicyInput.ProtoReflect.Descriptor instead. +func (*PolicyInput) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{4} +} -func (m *PolicyInput) GetScheme() string { - if m != nil { - return m.Scheme +func (x *PolicyInput) GetScheme() string { + if x != nil { + return x.Scheme } return "" } -func (m *PolicyInput) GetUrlStyle() UrlStyle { - if m != nil { - return m.UrlStyle +func (x *PolicyInput) GetUrlStyle() UrlStyle { + if x != nil { + return x.UrlStyle } return UrlStyle_PATH_STYLE } -func (m *PolicyInput) GetBucketBoundHostname() string { - if m != nil { - return m.BucketBoundHostname +func (x *PolicyInput) GetBucketBoundHostname() string { + if x != nil { + return x.BucketBoundHostname } return "" } -func (m *PolicyInput) GetBucket() string { - if m != nil { - return m.Bucket +func (x *PolicyInput) GetBucket() string { + if x != nil { + return x.Bucket } return "" } -func (m *PolicyInput) GetObject() string { - if m != nil { - return m.Object +func (x *PolicyInput) GetObject() string { + if x != nil { + return x.Object } return "" } -func (m *PolicyInput) GetExpiration() int32 { - if m != nil { - return m.Expiration +func (x *PolicyInput) GetExpiration() int32 { + if x != nil { + return x.Expiration } return 0 } -func (m *PolicyInput) GetTimestamp() *timestamp.Timestamp { - if m != nil { - return m.Timestamp +func (x *PolicyInput) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp } return nil } -func (m *PolicyInput) GetFields() map[string]string { - if m != nil { - return m.Fields +func (x *PolicyInput) GetFields() map[string]string { + if x != nil { + return x.Fields } return nil } -func (m *PolicyInput) GetConditions() *PolicyConditions { - if m != nil { - return m.Conditions +func (x *PolicyInput) GetConditions() *PolicyConditions { + if x != nil { + return x.Conditions } return nil } type PolicyOutput struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` Fields map[string]string `protobuf:"bytes,2,rep,name=fields,proto3" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` ExpectedDecodedPolicy string `protobuf:"bytes,3,opt,name=expectedDecodedPolicy,proto3" json:"expectedDecodedPolicy,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` } -func (m *PolicyOutput) Reset() { *m = PolicyOutput{} } -func (m *PolicyOutput) String() string { return proto.CompactTextString(m) } -func (*PolicyOutput) ProtoMessage() {} +func (x *PolicyOutput) Reset() { + *x = PolicyOutput{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PolicyOutput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicyOutput) ProtoMessage() {} + +func (x *PolicyOutput) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[5] + 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 PolicyOutput.ProtoReflect.Descriptor instead. func (*PolicyOutput) Descriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{5} + return file_test_proto_rawDescGZIP(), []int{5} +} + +func (x *PolicyOutput) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *PolicyOutput) GetFields() map[string]string { + if x != nil { + return x.Fields + } + return nil } -func (m *PolicyOutput) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PolicyOutput.Unmarshal(m, b) +func (x *PolicyOutput) GetExpectedDecodedPolicy() string { + if x != nil { + return x.ExpectedDecodedPolicy + } + return "" } -func (m *PolicyOutput) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PolicyOutput.Marshal(b, m, deterministic) + +type PostPolicyV4Test struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + PolicyInput *PolicyInput `protobuf:"bytes,2,opt,name=policyInput,proto3" json:"policyInput,omitempty"` + PolicyOutput *PolicyOutput `protobuf:"bytes,3,opt,name=policyOutput,proto3" json:"policyOutput,omitempty"` } -func (m *PolicyOutput) XXX_Merge(src proto.Message) { - xxx_messageInfo_PolicyOutput.Merge(m, src) + +func (x *PostPolicyV4Test) Reset() { + *x = PostPolicyV4Test{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *PolicyOutput) XXX_Size() int { - return xxx_messageInfo_PolicyOutput.Size(m) + +func (x *PostPolicyV4Test) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *PolicyOutput) XXX_DiscardUnknown() { - xxx_messageInfo_PolicyOutput.DiscardUnknown(m) + +func (*PostPolicyV4Test) ProtoMessage() {} + +func (x *PostPolicyV4Test) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[6] + 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) } -var xxx_messageInfo_PolicyOutput proto.InternalMessageInfo +// Deprecated: Use PostPolicyV4Test.ProtoReflect.Descriptor instead. +func (*PostPolicyV4Test) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{6} +} -func (m *PolicyOutput) GetUrl() string { - if m != nil { - return m.Url +func (x *PostPolicyV4Test) GetDescription() string { + if x != nil { + return x.Description } return "" } -func (m *PolicyOutput) GetFields() map[string]string { - if m != nil { - return m.Fields +func (x *PostPolicyV4Test) GetPolicyInput() *PolicyInput { + if x != nil { + return x.PolicyInput } return nil } -func (m *PolicyOutput) GetExpectedDecodedPolicy() string { - if m != nil { - return m.ExpectedDecodedPolicy +func (x *PostPolicyV4Test) GetPolicyOutput() *PolicyOutput { + if x != nil { + return x.PolicyOutput } - return "" + return nil } -type PostPolicyV4Test struct { - Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` - PolicyInput *PolicyInput `protobuf:"bytes,2,opt,name=policyInput,proto3" json:"policyInput,omitempty"` - PolicyOutput *PolicyOutput `protobuf:"bytes,3,opt,name=policyOutput,proto3" json:"policyOutput,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type RetryTests struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RetryTests []*RetryTest `protobuf:"bytes,1,rep,name=retryTests,proto3" json:"retryTests,omitempty"` } -func (m *PostPolicyV4Test) Reset() { *m = PostPolicyV4Test{} } -func (m *PostPolicyV4Test) String() string { return proto.CompactTextString(m) } -func (*PostPolicyV4Test) ProtoMessage() {} -func (*PostPolicyV4Test) Descriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{6} +func (x *RetryTests) Reset() { + *x = RetryTests{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RetryTests) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RetryTests) ProtoMessage() {} + +func (x *RetryTests) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[7] + 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 RetryTests.ProtoReflect.Descriptor instead. +func (*RetryTests) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{7} +} + +func (x *RetryTests) GetRetryTests() []*RetryTest { + if x != nil { + return x.RetryTests + } + return nil +} + +// A list of instructions to send as headers to the GCS emulator. Each +// instruction will force a specified failure for that request. +type InstructionList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Instructions []string `protobuf:"bytes,1,rep,name=instructions,proto3" json:"instructions,omitempty"` +} + +func (x *InstructionList) Reset() { + *x = InstructionList{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InstructionList) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *PostPolicyV4Test) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PostPolicyV4Test.Unmarshal(m, b) +func (*InstructionList) ProtoMessage() {} + +func (x *InstructionList) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[8] + 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 InstructionList.ProtoReflect.Descriptor instead. +func (*InstructionList) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{8} +} + +func (x *InstructionList) GetInstructions() []string { + if x != nil { + return x.Instructions + } + return nil +} + +// A particular storage API method and required resources in order to test it. +// Methods must be implemented in tests for each language. +type Method struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // e.g. storage.objects.get + Resources []Resource `protobuf:"varint,2,rep,packed,name=resources,proto3,enum=google.cloud.conformance.storage.v1.Resource" json:"resources,omitempty"` +} + +func (x *Method) Reset() { + *x = Method{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Method) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Method) ProtoMessage() {} + +func (x *Method) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[9] + 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 Method.ProtoReflect.Descriptor instead. +func (*Method) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{9} +} + +func (x *Method) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Method) GetResources() []Resource { + if x != nil { + return x.Resources + } + return nil } -func (m *PostPolicyV4Test) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PostPolicyV4Test.Marshal(b, m, deterministic) + +// Schema for a retry test, corresponding to a single scenario from the design +// doc. +type RetryTest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Scenario number + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + // Human-readable description of the test case. + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // list of emulator instruction sets. + Cases []*InstructionList `protobuf:"bytes,3,rep,name=cases,proto3" json:"cases,omitempty"` + // List of API methods to be tested. + Methods []*Method `protobuf:"bytes,4,rep,name=methods,proto3" json:"methods,omitempty"` + // Whether a precondition is provided (for conditionally-idempotent methods + // only). + PreconditionProvided bool `protobuf:"varint,5,opt,name=preconditionProvided,proto3" json:"preconditionProvided,omitempty"` + // Whether we expect the method calls to eventually succeed after the client + // library retries. + ExpectSuccess bool `protobuf:"varint,6,opt,name=expectSuccess,proto3" json:"expectSuccess,omitempty"` +} + +func (x *RetryTest) Reset() { + *x = RetryTest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *PostPolicyV4Test) XXX_Merge(src proto.Message) { - xxx_messageInfo_PostPolicyV4Test.Merge(m, src) + +func (x *RetryTest) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *PostPolicyV4Test) XXX_Size() int { - return xxx_messageInfo_PostPolicyV4Test.Size(m) + +func (*RetryTest) ProtoMessage() {} + +func (x *RetryTest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[10] + 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) } -func (m *PostPolicyV4Test) XXX_DiscardUnknown() { - xxx_messageInfo_PostPolicyV4Test.DiscardUnknown(m) + +// Deprecated: Use RetryTest.ProtoReflect.Descriptor instead. +func (*RetryTest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{10} } -var xxx_messageInfo_PostPolicyV4Test proto.InternalMessageInfo +func (x *RetryTest) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} -func (m *PostPolicyV4Test) GetDescription() string { - if m != nil { - return m.Description +func (x *RetryTest) GetDescription() string { + if x != nil { + return x.Description } return "" } -func (m *PostPolicyV4Test) GetPolicyInput() *PolicyInput { - if m != nil { - return m.PolicyInput +func (x *RetryTest) GetCases() []*InstructionList { + if x != nil { + return x.Cases } return nil } -func (m *PostPolicyV4Test) GetPolicyOutput() *PolicyOutput { - if m != nil { - return m.PolicyOutput +func (x *RetryTest) GetMethods() []*Method { + if x != nil { + return x.Methods } return nil } -func init() { - proto.RegisterEnum("google.cloud.conformance.storage.v1.UrlStyle", UrlStyle_name, UrlStyle_value) - proto.RegisterType((*TestFile)(nil), "google.cloud.conformance.storage.v1.TestFile") - proto.RegisterType((*SigningV4Test)(nil), "google.cloud.conformance.storage.v1.SigningV4Test") - proto.RegisterMapType((map[string]string)(nil), "google.cloud.conformance.storage.v1.SigningV4Test.HeadersEntry") - proto.RegisterMapType((map[string]string)(nil), "google.cloud.conformance.storage.v1.SigningV4Test.QueryParametersEntry") - proto.RegisterType((*ConditionalMatches)(nil), "google.cloud.conformance.storage.v1.ConditionalMatches") - proto.RegisterType((*PolicyConditions)(nil), "google.cloud.conformance.storage.v1.PolicyConditions") - proto.RegisterType((*PolicyInput)(nil), "google.cloud.conformance.storage.v1.PolicyInput") - proto.RegisterMapType((map[string]string)(nil), "google.cloud.conformance.storage.v1.PolicyInput.FieldsEntry") - proto.RegisterType((*PolicyOutput)(nil), "google.cloud.conformance.storage.v1.PolicyOutput") - proto.RegisterMapType((map[string]string)(nil), "google.cloud.conformance.storage.v1.PolicyOutput.FieldsEntry") - proto.RegisterType((*PostPolicyV4Test)(nil), "google.cloud.conformance.storage.v1.PostPolicyV4Test") -} - -func init() { proto.RegisterFile("test.proto", fileDescriptor_c161fcfdc0c3ff1e) } - -var fileDescriptor_c161fcfdc0c3ff1e = []byte{ - // 901 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xef, 0x6e, 0xe2, 0x46, - 0x10, 0xaf, 0x21, 0x70, 0x30, 0xe4, 0x72, 0x74, 0xcb, 0x55, 0x2e, 0x1f, 0x5a, 0x44, 0x3f, 0x94, - 0x56, 0xaa, 0xef, 0x42, 0x73, 0xd2, 0x35, 0x6a, 0x55, 0x05, 0xc2, 0x5d, 0xa2, 0xe6, 0x12, 0x6a, - 0x4c, 0x4e, 0x27, 0x55, 0x42, 0xc6, 0x1e, 0xc0, 0x3d, 0xe3, 0x75, 0xbc, 0xeb, 0xe8, 0x78, 0x8f, - 0x3e, 0x45, 0x9f, 0xa6, 0x6f, 0xd0, 0x4f, 0x95, 0xfa, 0x18, 0xd5, 0xee, 0xda, 0x60, 0x2e, 0x44, - 0x82, 0xfe, 0xf9, 0xc6, 0xcc, 0xec, 0xfc, 0x7e, 0xeb, 0x99, 0xdf, 0xcc, 0x02, 0xc0, 0x91, 0x71, - 0x23, 0x8c, 0x28, 0xa7, 0xe4, 0xf3, 0x29, 0xa5, 0x53, 0x1f, 0x0d, 0xc7, 0xa7, 0xb1, 0x6b, 0x38, - 0x34, 0x98, 0xd0, 0x68, 0x6e, 0x07, 0x0e, 0x1a, 0x8c, 0xd3, 0xc8, 0x9e, 0xa2, 0x71, 0x7b, 0x58, - 0xff, 0x4c, 0x1d, 0x7a, 0x22, 0x53, 0xc6, 0xf1, 0xe4, 0x09, 0xf7, 0xe6, 0xc8, 0xb8, 0x3d, 0x0f, - 0x15, 0x4a, 0xf3, 0x77, 0x0d, 0x4a, 0x16, 0x32, 0xfe, 0xc2, 0xf3, 0x91, 0xfc, 0x0c, 0x55, 0xe6, - 0x4d, 0x03, 0x2f, 0x98, 0x8e, 0x6e, 0x8f, 0x46, 0x82, 0x8b, 0xe9, 0x5a, 0x23, 0xdf, 0xaa, 0xb4, - 0xdb, 0xc6, 0x16, 0x6c, 0xc6, 0x40, 0x25, 0x5f, 0x1f, 0x09, 0x44, 0xf3, 0x80, 0x65, 0x4d, 0x46, - 0x26, 0x50, 0x0b, 0x29, 0xe3, 0xa3, 0x90, 0xfa, 0x9e, 0xb3, 0x58, 0x31, 0xe4, 0x24, 0xc3, 0xb3, - 0xad, 0x18, 0xfa, 0x94, 0xf1, 0xbe, 0xcc, 0x4f, 0x48, 0x3e, 0x0c, 0xdf, 0xf3, 0xb0, 0xe6, 0x9f, - 0x45, 0x78, 0xb8, 0x76, 0x13, 0x52, 0x87, 0xd2, 0xc4, 0xf3, 0xf1, 0xd2, 0x9e, 0xa3, 0xae, 0x35, - 0xb4, 0x56, 0xd9, 0x5c, 0xda, 0xa4, 0x01, 0x15, 0x17, 0x99, 0x13, 0x79, 0x21, 0xf7, 0x68, 0xa0, - 0xe7, 0x64, 0x38, 0xeb, 0x22, 0x1f, 0x43, 0x71, 0x1c, 0x3b, 0x6f, 0x91, 0xeb, 0x79, 0x19, 0x4c, - 0x2c, 0xe1, 0xa7, 0xe3, 0x5f, 0xd0, 0xe1, 0xfa, 0x9e, 0xf2, 0x2b, 0x4b, 0xf8, 0xe7, 0xc8, 0x67, - 0xd4, 0xd5, 0x0b, 0xca, 0xaf, 0x2c, 0xf2, 0x29, 0x00, 0xbe, 0x0b, 0xbd, 0xc8, 0x96, 0x44, 0xc5, - 0x86, 0xd6, 0xca, 0x9b, 0x19, 0x0f, 0x79, 0x0e, 0xe5, 0x65, 0x77, 0xf4, 0x07, 0x0d, 0xad, 0x55, - 0x69, 0xd7, 0xd3, 0xa2, 0xa4, 0xfd, 0x33, 0xac, 0xf4, 0x84, 0xb9, 0x3a, 0x2c, 0xbe, 0x01, 0xdf, - 0x85, 0xe8, 0x70, 0x74, 0x87, 0x91, 0xaf, 0x97, 0xd4, 0x37, 0x64, 0x5c, 0xe4, 0x0d, 0x3c, 0x98, - 0xa1, 0xed, 0x62, 0xc4, 0xf4, 0xb2, 0x2c, 0xf7, 0x0f, 0xbb, 0x37, 0xd4, 0x38, 0x53, 0x08, 0xbd, - 0x80, 0x47, 0x0b, 0x33, 0xc5, 0x23, 0x11, 0x54, 0x6f, 0x62, 0x8c, 0x16, 0xa3, 0xd0, 0x8e, 0xec, - 0x39, 0x72, 0xc1, 0x01, 0x92, 0xe3, 0xe5, 0x3f, 0xe0, 0xf8, 0x49, 0x40, 0xf5, 0x97, 0x48, 0x8a, - 0xeb, 0xd1, 0xcd, 0xba, 0x57, 0x94, 0x98, 0x39, 0x33, 0x9c, 0xa3, 0x5e, 0x51, 0x25, 0x56, 0x16, - 0x39, 0x87, 0x52, 0x1c, 0xf9, 0x03, 0xbe, 0xf0, 0x51, 0xdf, 0x6f, 0x68, 0xad, 0x83, 0xf6, 0xd7, - 0x5b, 0xdd, 0x61, 0x98, 0x24, 0x99, 0xcb, 0x74, 0xf2, 0x14, 0x3e, 0x52, 0x7d, 0xee, 0xd0, 0x38, - 0x70, 0xcf, 0x28, 0xe3, 0x81, 0x90, 0xcf, 0x43, 0xc9, 0xb7, 0x29, 0x44, 0x8e, 0x41, 0x4f, 0x4b, - 0xde, 0xb5, 0x03, 0x1a, 0x78, 0x8e, 0xed, 0x9b, 0x78, 0x13, 0x23, 0xe3, 0xfa, 0x81, 0x4c, 0xbb, - 0x37, 0x4e, 0xda, 0x50, 0x4b, 0x63, 0x03, 0x1e, 0x79, 0xc1, 0xd4, 0xa2, 0xa2, 0x2e, 0xfa, 0x23, - 0x99, 0xb7, 0x31, 0x56, 0x3f, 0x86, 0xfd, 0x6c, 0x47, 0x48, 0x15, 0xf2, 0x6f, 0x71, 0x91, 0x08, - 0x5c, 0xfc, 0x24, 0x35, 0x28, 0xdc, 0xda, 0x7e, 0x8c, 0x89, 0xaa, 0x95, 0x71, 0x9c, 0x7b, 0xae, - 0xd5, 0x3b, 0x50, 0xdb, 0x54, 0xe9, 0x5d, 0x30, 0x9a, 0x47, 0x40, 0xba, 0x34, 0x70, 0x3d, 0x21, - 0x5e, 0xdb, 0x7f, 0x65, 0x73, 0x67, 0x86, 0x2c, 0x51, 0x79, 0x84, 0x8c, 0x09, 0x95, 0x8b, 0xed, - 0x51, 0x36, 0x33, 0x9e, 0xe6, 0x18, 0xaa, 0x6a, 0x5c, 0x97, 0xb9, 0x8c, 0x18, 0x40, 0x1c, 0x1a, - 0x70, 0x0c, 0xf8, 0x05, 0x06, 0x53, 0x3e, 0x33, 0xed, 0x60, 0x8a, 0x32, 0xb7, 0x60, 0x6e, 0x88, - 0x08, 0x0e, 0xc6, 0xed, 0x88, 0xb3, 0xd7, 0x1e, 0x9f, 0xc9, 0xfd, 0x51, 0x36, 0x33, 0x9e, 0xe6, - 0xaf, 0x7b, 0x50, 0x51, 0x24, 0xe7, 0x41, 0x18, 0xf3, 0x8c, 0x5c, 0xb4, 0x7b, 0xe5, 0x92, 0xfb, - 0x5f, 0xe4, 0x92, 0xbf, 0x5f, 0x2e, 0xab, 0xb5, 0xb2, 0x77, 0xcf, 0x5a, 0x29, 0xac, 0xad, 0x95, - 0xbb, 0xeb, 0xa3, 0xf0, 0x1f, 0xad, 0x0f, 0x0b, 0x8a, 0x13, 0x0f, 0x7d, 0x97, 0xe9, 0x25, 0x39, - 0xb7, 0xdf, 0x6d, 0xb9, 0x8a, 0x97, 0x05, 0x36, 0x5e, 0xc8, 0x74, 0x35, 0xac, 0x09, 0x16, 0x19, - 0x02, 0x38, 0xcb, 0x16, 0xeb, 0x65, 0x79, 0xa1, 0x67, 0x3b, 0x20, 0xaf, 0xf4, 0x61, 0x66, 0x80, - 0xea, 0xdf, 0x42, 0x25, 0xc3, 0xb6, 0x93, 0x60, 0xff, 0xd2, 0x60, 0x5f, 0x61, 0x5f, 0xc5, 0x5c, - 0xe8, 0xa2, 0x0a, 0xf9, 0x38, 0xf2, 0xd3, 0xe4, 0x38, 0xf2, 0xc9, 0x70, 0x59, 0x0a, 0xf5, 0x2a, - 0x7d, 0xbf, 0xc3, 0x85, 0x15, 0xe8, 0xc6, 0x5a, 0x1c, 0xc1, 0xe3, 0x74, 0x84, 0x4f, 0xd1, 0xa1, - 0x2e, 0xba, 0x2a, 0x25, 0xd1, 0xc7, 0xe6, 0xe0, 0xbf, 0xf9, 0xd4, 0x3f, 0x34, 0x31, 0x66, 0xeb, - 0x2f, 0xe3, 0xfb, 0x4f, 0x9d, 0x76, 0xf7, 0xa9, 0x33, 0xa1, 0x12, 0xae, 0xda, 0x2a, 0x61, 0x2b, - 0xed, 0xa7, 0xbb, 0xca, 0xc1, 0xcc, 0x82, 0x90, 0x21, 0xec, 0x87, 0x99, 0xfa, 0xc8, 0x4f, 0xae, - 0xb4, 0x0f, 0x77, 0x2e, 0xac, 0xb9, 0x06, 0xf3, 0xd5, 0x15, 0x94, 0xd2, 0x31, 0x24, 0x07, 0x00, - 0xfd, 0x13, 0xeb, 0x6c, 0x34, 0xb0, 0xde, 0x5c, 0xf4, 0xaa, 0x1f, 0x10, 0x1d, 0x6a, 0xd7, 0xe7, - 0xa6, 0x35, 0x3c, 0xb9, 0x18, 0x9d, 0x5d, 0x0d, 0xac, 0xde, 0x69, 0x12, 0xd1, 0xc8, 0x27, 0xf0, - 0xb8, 0x33, 0xec, 0xfe, 0xd8, 0xb3, 0x46, 0x9d, 0xab, 0xe1, 0xe5, 0xa9, 0x0c, 0x5f, 0x9e, 0xbc, - 0xea, 0x55, 0x73, 0x9d, 0xd7, 0xf0, 0x85, 0x43, 0xe7, 0xdb, 0x5c, 0xab, 0xaf, 0xfd, 0x96, 0xfb, - 0xf2, 0xa5, 0x3a, 0xd7, 0x95, 0xe7, 0x06, 0x49, 0xec, 0xfa, 0xd0, 0x90, 0xff, 0x41, 0x8c, 0xee, - 0x2a, 0x71, 0x5c, 0x94, 0xd3, 0xf7, 0xcd, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x35, 0x7d, - 0xfd, 0xbd, 0x09, 0x00, 0x00, +func (x *RetryTest) GetPreconditionProvided() bool { + if x != nil { + return x.PreconditionProvided + } + return false +} + +func (x *RetryTest) GetExpectSuccess() bool { + if x != nil { + return x.ExpectSuccess + } + return false +} + +var File_test_proto protoreflect.FileDescriptor + +var file_test_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, + 0x31, 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, 0xa1, 0x02, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, + 0x5c, 0x0a, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x34, 0x5f, 0x74, 0x65, + 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x56, 0x34, 0x54, 0x65, 0x73, 0x74, 0x52, 0x0e, 0x73, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x56, 0x34, 0x54, 0x65, 0x73, 0x74, 0x73, 0x12, 0x66, 0x0a, + 0x14, 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x34, 0x5f, + 0x74, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x34, 0x54, 0x65, + 0x73, 0x74, 0x52, 0x11, 0x70, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x34, + 0x54, 0x65, 0x73, 0x74, 0x73, 0x12, 0x4f, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x74, + 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x54, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x72, 0x65, 0x74, 0x72, + 0x79, 0x54, 0x65, 0x73, 0x74, 0x73, 0x22, 0xe5, 0x06, 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x56, 0x34, 0x54, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1e, + 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, + 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 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, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x65, + 0x63, 0x74, 0x65, 0x64, 0x55, 0x72, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, + 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x59, 0x0a, 0x07, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x56, 0x34, 0x54, 0x65, 0x73, 0x74, 0x2e, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x72, 0x0a, 0x10, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x47, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x56, 0x34, 0x54, + 0x65, 0x73, 0x74, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, + 0x65, 0x12, 0x49, 0x0a, 0x08, 0x75, 0x72, 0x6c, 0x53, 0x74, 0x79, 0x6c, 0x65, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x72, 0x6c, 0x53, 0x74, 0x79, + 0x6c, 0x65, 0x52, 0x08, 0x75, 0x72, 0x6c, 0x53, 0x74, 0x79, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x13, + 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x62, 0x75, 0x63, 0x6b, 0x65, + 0x74, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, + 0x0a, 0x18, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, + 0x63, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x18, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, + 0x63, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x14, 0x65, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x53, 0x69, + 0x67, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x53, 0x69, 0x67, 0x6e, 0x1a, 0x3a, + 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x42, 0x0a, 0x14, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x34, + 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x62, 0x0a, 0x10, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x6f, + 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x05, 0x52, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x73, 0x57, 0x69, 0x74, 0x68, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x73, 0x57, 0x69, 0x74, 0x68, 0x22, 0x94, 0x04, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, + 0x12, 0x49, 0x0a, 0x08, 0x75, 0x72, 0x6c, 0x53, 0x74, 0x79, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x72, 0x6c, 0x53, 0x74, 0x79, 0x6c, + 0x65, 0x52, 0x08, 0x75, 0x72, 0x6c, 0x53, 0x74, 0x79, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x62, + 0x75, 0x63, 0x6b, 0x65, 0x74, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, + 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, + 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1e, 0x0a, + 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 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, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x54, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, + 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x55, 0x0a, + 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x6f, + 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0xe8, 0x01, 0x0a, 0x0c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, + 0x72, 0x6c, 0x12, 0x55, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x65, 0x78, 0x70, + 0x65, 0x63, 0x74, 0x65, 0x64, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x1a, + 0x39, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdf, 0x01, 0x0a, 0x10, 0x50, + 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x34, 0x54, 0x65, 0x73, 0x74, 0x12, + 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x52, 0x0a, 0x0b, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, + 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x0b, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x55, 0x0a, 0x0c, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x0c, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0x5c, 0x0a, 0x0a, + 0x52, 0x65, 0x74, 0x72, 0x79, 0x54, 0x65, 0x73, 0x74, 0x73, 0x12, 0x4e, 0x0a, 0x0a, 0x72, 0x65, + 0x74, 0x72, 0x79, 0x54, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x54, 0x65, 0x73, 0x74, 0x52, 0x0a, + 0x72, 0x65, 0x74, 0x72, 0x79, 0x54, 0x65, 0x73, 0x74, 0x73, 0x22, 0x35, 0x0a, 0x0f, 0x49, 0x6e, + 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x22, 0x0a, + 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x22, 0x69, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x4b, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0xaa, 0x02, 0x0a, + 0x09, 0x52, 0x65, 0x74, 0x72, 0x79, 0x54, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x05, + 0x63, 0x61, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x05, 0x63, 0x61, 0x73, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x12, + 0x32, 0x0a, 0x14, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x70, + 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x53, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, + 0x63, 0x74, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2a, 0x4f, 0x0a, 0x08, 0x55, 0x72, 0x6c, + 0x53, 0x74, 0x79, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x41, 0x54, 0x48, 0x5f, 0x53, 0x54, + 0x59, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x49, 0x52, 0x54, 0x55, 0x41, 0x4c, + 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x5f, 0x53, 0x54, 0x59, 0x4c, 0x45, 0x10, 0x01, 0x12, + 0x19, 0x0a, 0x15, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x5f, + 0x48, 0x4f, 0x53, 0x54, 0x4e, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x2a, 0x42, 0x0a, 0x08, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, + 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x10, + 0x0a, 0x0c, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, + 0x12, 0x0c, 0x0a, 0x08, 0x48, 0x4d, 0x41, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x03, 0x42, 0x7c, + 0x0a, 0x27, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x73, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x50, 0x01, 0x5a, 0x23, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x31, + 0xaa, 0x02, 0x29, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x56, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x73, + 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_test_proto_rawDescOnce sync.Once + file_test_proto_rawDescData = file_test_proto_rawDesc +) + +func file_test_proto_rawDescGZIP() []byte { + file_test_proto_rawDescOnce.Do(func() { + file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData) + }) + return file_test_proto_rawDescData +} + +var file_test_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_test_proto_goTypes = []interface{}{ + (UrlStyle)(0), // 0: google.cloud.conformance.storage.v1.UrlStyle + (Resource)(0), // 1: google.cloud.conformance.storage.v1.Resource + (*TestFile)(nil), // 2: google.cloud.conformance.storage.v1.TestFile + (*SigningV4Test)(nil), // 3: google.cloud.conformance.storage.v1.SigningV4Test + (*ConditionalMatches)(nil), // 4: google.cloud.conformance.storage.v1.ConditionalMatches + (*PolicyConditions)(nil), // 5: google.cloud.conformance.storage.v1.PolicyConditions + (*PolicyInput)(nil), // 6: google.cloud.conformance.storage.v1.PolicyInput + (*PolicyOutput)(nil), // 7: google.cloud.conformance.storage.v1.PolicyOutput + (*PostPolicyV4Test)(nil), // 8: google.cloud.conformance.storage.v1.PostPolicyV4Test + (*RetryTests)(nil), // 9: google.cloud.conformance.storage.v1.RetryTests + (*InstructionList)(nil), // 10: google.cloud.conformance.storage.v1.InstructionList + (*Method)(nil), // 11: google.cloud.conformance.storage.v1.Method + (*RetryTest)(nil), // 12: google.cloud.conformance.storage.v1.RetryTest + nil, // 13: google.cloud.conformance.storage.v1.SigningV4Test.HeadersEntry + nil, // 14: google.cloud.conformance.storage.v1.SigningV4Test.QueryParametersEntry + nil, // 15: google.cloud.conformance.storage.v1.PolicyInput.FieldsEntry + nil, // 16: google.cloud.conformance.storage.v1.PolicyOutput.FieldsEntry + (*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp +} +var file_test_proto_depIdxs = []int32{ + 3, // 0: google.cloud.conformance.storage.v1.TestFile.signing_v4_tests:type_name -> google.cloud.conformance.storage.v1.SigningV4Test + 8, // 1: google.cloud.conformance.storage.v1.TestFile.post_policy_v4_tests:type_name -> google.cloud.conformance.storage.v1.PostPolicyV4Test + 12, // 2: google.cloud.conformance.storage.v1.TestFile.retry_tests:type_name -> google.cloud.conformance.storage.v1.RetryTest + 17, // 3: google.cloud.conformance.storage.v1.SigningV4Test.timestamp:type_name -> google.protobuf.Timestamp + 13, // 4: google.cloud.conformance.storage.v1.SigningV4Test.headers:type_name -> google.cloud.conformance.storage.v1.SigningV4Test.HeadersEntry + 14, // 5: google.cloud.conformance.storage.v1.SigningV4Test.query_parameters:type_name -> google.cloud.conformance.storage.v1.SigningV4Test.QueryParametersEntry + 0, // 6: google.cloud.conformance.storage.v1.SigningV4Test.urlStyle:type_name -> google.cloud.conformance.storage.v1.UrlStyle + 0, // 7: google.cloud.conformance.storage.v1.PolicyInput.urlStyle:type_name -> google.cloud.conformance.storage.v1.UrlStyle + 17, // 8: google.cloud.conformance.storage.v1.PolicyInput.timestamp:type_name -> google.protobuf.Timestamp + 15, // 9: google.cloud.conformance.storage.v1.PolicyInput.fields:type_name -> google.cloud.conformance.storage.v1.PolicyInput.FieldsEntry + 5, // 10: google.cloud.conformance.storage.v1.PolicyInput.conditions:type_name -> google.cloud.conformance.storage.v1.PolicyConditions + 16, // 11: google.cloud.conformance.storage.v1.PolicyOutput.fields:type_name -> google.cloud.conformance.storage.v1.PolicyOutput.FieldsEntry + 6, // 12: google.cloud.conformance.storage.v1.PostPolicyV4Test.policyInput:type_name -> google.cloud.conformance.storage.v1.PolicyInput + 7, // 13: google.cloud.conformance.storage.v1.PostPolicyV4Test.policyOutput:type_name -> google.cloud.conformance.storage.v1.PolicyOutput + 12, // 14: google.cloud.conformance.storage.v1.RetryTests.retryTests:type_name -> google.cloud.conformance.storage.v1.RetryTest + 1, // 15: google.cloud.conformance.storage.v1.Method.resources:type_name -> google.cloud.conformance.storage.v1.Resource + 10, // 16: google.cloud.conformance.storage.v1.RetryTest.cases:type_name -> google.cloud.conformance.storage.v1.InstructionList + 11, // 17: google.cloud.conformance.storage.v1.RetryTest.methods:type_name -> google.cloud.conformance.storage.v1.Method + 18, // [18:18] is the sub-list for method output_type + 18, // [18:18] is the sub-list for method input_type + 18, // [18:18] is the sub-list for extension type_name + 18, // [18:18] is the sub-list for extension extendee + 0, // [0:18] is the sub-list for field type_name +} + +func init() { file_test_proto_init() } +func file_test_proto_init() { + if File_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestFile); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SigningV4Test); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ConditionalMatches); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PolicyConditions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PolicyInput); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PolicyOutput); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PostPolicyV4Test); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RetryTests); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InstructionList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Method); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RetryTest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_test_proto_rawDesc, + NumEnums: 2, + NumMessages: 15, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_test_proto_goTypes, + DependencyIndexes: file_test_proto_depIdxs, + EnumInfos: file_test_proto_enumTypes, + MessageInfos: file_test_proto_msgTypes, + }.Build() + File_test_proto = out.File + file_test_proto_rawDesc = nil + file_test_proto_goTypes = nil + file_test_proto_depIdxs = nil } diff --git a/storage/internal/test/conformance/test.proto b/storage/internal/test/conformance/test.proto index 49e913bff40..b7f440c7cbf 100644 --- a/storage/internal/test/conformance/test.proto +++ b/storage/internal/test/conformance/test.proto @@ -21,10 +21,12 @@ import "google/protobuf/timestamp.proto"; option csharp_namespace = "Google.Cloud.Storage.V1.Tests.Conformance"; option java_package = "com.google.cloud.conformance.storage.v1"; option java_multiple_files = true; +option go_package = "google/cloud/conformance/storage/v1"; message TestFile { repeated SigningV4Test signing_v4_tests = 1; repeated PostPolicyV4Test post_policy_v4_tests = 2; + repeated RetryTest retry_tests = 3; } enum UrlStyle { @@ -60,7 +62,11 @@ message PolicyConditions { repeated string startsWith = 2; } +// Specification documentation is located at: +// https://cloud.google.com/storage/docs/authentication/signatures + message PolicyInput { + // http or https string scheme = 1; UrlStyle urlStyle = 2; string bucketBoundHostname = 3; @@ -68,6 +74,15 @@ message PolicyInput { string object = 5; int32 expiration = 6; google.protobuf.Timestamp timestamp = 7; + /* + fields with strict equivalence which are added into + PolicyOutput.expectedDecodedPolicy to generate the + signature. + Expectations + E.1: Order them in lexigraphical order so it's the + signature can be verified across different language + implementations. + */ map fields = 8; PolicyConditions conditions = 9; } @@ -75,6 +90,54 @@ message PolicyInput { message PolicyOutput { string url = 1; map fields = 2; + /* + Expectations + E.1: PolicyInput.fields must be prepended to form expectedDecodedPolicy + for consistent result across languages. Ordering doesn't matter to the + service but the decision is made to make it easier to conform implementations + in implementation. + Example: + # Step 1 + PolicyInput.fields has: + { + "content-disposition":"attachment; filename=\"~._-%=/é0Aa\"", + "content-encoding":"gzip", + "content-type":"text/plain", + "success_action_redirect":"http://www.google.com/" + } + # Step 2 + The expectedDecodedPolicy before prepending the PolicyInput.fields + would look like this: + { + "conditions":[ + ...prepend here in the same order provided in PolicyInput.fields... + {"bucket":"bucket-name"}, + {"key":"test-object"}, + {"x-goog-date":"20200123T043530Z"}, + {"x-goog-credential":"test-iam-credentials@dummy-project-id.iam.gserviceaccount.com/20200123/auto/storage/goog4_request"}, + {"x-goog-algorithm":"GOOG4-RSA-SHA256"} + ], + "expiration":"2020-01-23T04:35:40Z" + } + # Step 3 + Then expectedDecodedPolicy should prepends PolicyInput.fields in + the same order to PolicyOutput.expectedDecodedPolicy `conditions` key. + { + "conditions":[ + {"content-disposition":"attachment; filename=\"~._-%=/é0Aa\""}, + {"content-encoding":"gzip"}, + {"content-type":"text/plain"}, + {"success_action_redirect":"http://www.google.com/"}, + {"bucket":"bucket-name"}, + {"key":"test-object"}, + {"x-goog-date":"20200123T043530Z"}, + {"x-goog-credential":"test-iam-credentials@dummy-project-id.iam.gserviceaccount.com/20200123/auto/storage/goog4_request"}, + {"x-goog-algorithm":"GOOG4-RSA-SHA256"} + ], + "expiration":"2020-01-23T04:35:40Z" + } + */ + string expectedDecodedPolicy = 3; } @@ -83,3 +146,59 @@ message PostPolicyV4Test { PolicyInput policyInput = 2; PolicyOutput policyOutput = 3; } + +/* + ------------------------------------------------------------------------------ + Data types for retry conformance tests + ------------------------------------------------------------------------------ +*/ + +message RetryTests { + repeated RetryTest retryTests = 1; +} + +// A list of instructions to send as headers to the GCS emulator. Each +// instruction will force a specified failure for that request. +message InstructionList { + repeated string instructions = 1; +} + +// Test resources that are necessary for a method call. For example, +// storage.objects.get would require BUCKET and OBJECT. +enum Resource { + BUCKET = 0; + OBJECT = 1; + NOTIFICATION = 2; + HMAC_KEY = 3; +} + +// A particular storage API method and required resources in order to test it. +// Methods must be implemented in tests for each language. +message Method { + string name = 1; // e.g. storage.objects.get + repeated Resource resources = 2; +} + +// Schema for a retry test, corresponding to a single scenario from the design +// doc. +message RetryTest { + // Scenario number + int32 id = 1; + + // Human-readable description of the test case. + string description = 2; + + // list of emulator instruction sets. + repeated InstructionList cases = 3; + + // List of API methods to be tested. + repeated Method methods = 4; + + // Whether a precondition is provided (for conditionally-idempotent methods + // only). + bool preconditionProvided = 5; + + // Whether we expect the method calls to eventually succeed after the client + // library retries. + bool expectSuccess = 6; +} diff --git a/storage/retry_conformance_test.go b/storage/retry_conformance_test.go new file mode 100644 index 00000000000..894fb5fad09 --- /dev/null +++ b/storage/retry_conformance_test.go @@ -0,0 +1,318 @@ +// Copyright 2019 Google LLC +// +// 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. + +package storage + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "net/http/httputil" + "net/url" + "os" + "strings" + "testing" + + "cloud.google.com/go/internal/uid" + storage_v1_tests "cloud.google.com/go/storage/internal/test/conformance" + "google.golang.org/api/option" + raw "google.golang.org/api/storage/v1" + htransport "google.golang.org/api/transport/http" +) + +var ( + // Resource vars for retry tests + bucketIDs = uid.NewSpace("bucket", nil) + objectIDs = uid.NewSpace("object", nil) + notificationIDs = uid.NewSpace("notification", nil) + projectID = "my-project-id" + serviceAccountEmail = "my-sevice-account@my-project-id.iam.gserviceaccount.com" + randomBytesToWrite = []byte("abcdef") +) + +type retryFunc func(ctx context.Context, c *Client, fs *resources, preconditions bool) error + +// Methods to retry. This is a map whose keys are a string describing a standard +// API call (e.g. storage.objects.get) and values are a list of functions which +// wrap library methods that implement these calls. There may be multiple values +// because multiple library methods may use the same call (e.g. get could be a +// read or just a metadata get). +var methods = map[string][]retryFunc{ + "storage.buckets.get": { + func(ctx context.Context, c *Client, fs *resources, _ bool) error { + _, err := c.Bucket(fs.bucket.Name).Attrs(ctx) + return err + }, + }, +} + +func TestRetryConformance(t *testing.T) { + host := os.Getenv("STORAGE_EMULATOR_HOST") + if host == "" { + // This test is currently skipped in CI as the env variable is not set + // TODO: Add test to CI + t.Skip("This test must use the testbench emulator; set STORAGE_EMULATOR_HOST to run.") + } + endpoint, err := url.Parse(host) + if err != nil { + t.Fatalf("error parsing emulator host (make sure it includes the scheme such as http://host): %v", err) + } + + ctx := context.Background() + + // Create non-wrapped client to use for setup steps. + client, err := NewClient(ctx) + if err != nil { + t.Fatalf("storage.NewClient: %v", err) + } + + _, _, testFiles := parseFiles(t) + + for _, testFile := range testFiles { + for _, retryTest := range testFile.RetryTests { + for _, instructions := range retryTest.Cases { + for _, method := range retryTest.Methods { + if len(methods[method.Name]) == 0 { + t.Logf("No tests for operation %v", method.Name) + } + for i, fn := range methods[method.Name] { + testName := fmt.Sprintf("%v-%v-%v-%v", retryTest.Id, instructions.Instructions, method.Name, i) + t.Run(testName, func(t *testing.T) { + + // Create the retry subtest + subtest := &emulatorTest{T: t, name: testName, host: endpoint} + subtest.create(map[string][]string{ + method.Name: instructions.Instructions, + }) + + // Create necessary test resources in the emulator + subtest.populateResources(ctx, client, method.Resources) + + // Test + err = fn(ctx, subtest.wrappedClient, &subtest.resources, retryTest.PreconditionProvided) + if retryTest.ExpectSuccess && err != nil { + t.Errorf("want success, got %v", err) + } + if !retryTest.ExpectSuccess && err == nil { + t.Errorf("want failure, got success") + } + + // Verify that all instructions were used up during the test + // (indicates that the client sent the correct requests). + subtest.check() + + // Close out test in emulator. + subtest.delete() + }) + } + } + } + } + } +} + +type emulatorTest struct { + *testing.T + name string + id string // ID to pass as a header in the test execution + resources resources + host *url.URL // set the path when using; path is not guaranteed between calls + wrappedClient *Client +} + +// Holds the resources for a particular test case. Only the necessary fields will +// be populated; others will be nil. +type resources struct { + bucket *BucketAttrs + object *ObjectAttrs + notification *Notification + hmacKey *HMACKey +} + +// Creates given test resources with the provided client +func (et *emulatorTest) populateResources(ctx context.Context, c *Client, resources []storage_v1_tests.Resource) { + for _, resource := range resources { + switch resource { + case storage_v1_tests.Resource_BUCKET: + bkt := c.Bucket(bucketIDs.New()) + if err := bkt.Create(ctx, projectID, &BucketAttrs{}); err != nil { + et.Fatalf("creating bucket: %v", err) + } + attrs, err := bkt.Attrs(ctx) + if err != nil { + et.Fatalf("getting bucket attrs: %v", err) + } + et.resources.bucket = attrs + case storage_v1_tests.Resource_OBJECT: + // Assumes bucket has been populated first. + obj := c.Bucket(et.resources.bucket.Name).Object(objectIDs.New()) + w := obj.NewWriter(ctx) + if _, err := w.Write(randomBytesToWrite); err != nil { + et.Fatalf("writing object: %v", err) + } + if err := w.Close(); err != nil { + et.Fatalf("closing object: %v", err) + } + attrs, err := obj.Attrs(ctx) + if err != nil { + et.Fatalf("getting object attrs: %v", err) + } + et.resources.object = attrs + case storage_v1_tests.Resource_NOTIFICATION: + // Assumes bucket has been populated first. + n, err := c.Bucket(et.resources.bucket.Name).AddNotification(ctx, &Notification{ + TopicProjectID: projectID, + TopicID: notificationIDs.New(), + PayloadFormat: JSONPayload, + }) + if err != nil { + et.Fatalf("adding notification: %v", err) + } + et.resources.notification = n + case storage_v1_tests.Resource_HMAC_KEY: + key, err := c.CreateHMACKey(ctx, projectID, serviceAccountEmail) + if err != nil { + et.Fatalf("creating HMAC key: %v", err) + } + et.resources.hmacKey = key + } + } +} + +// Creates a retry test resource in the emulator +func (et *emulatorTest) create(instructions map[string][]string) { + c := http.DefaultClient + data := struct { + Instructions map[string][]string `json:"instructions"` + }{ + Instructions: instructions, + } + + buf := new(bytes.Buffer) + if err := json.NewEncoder(buf).Encode(data); err != nil { + et.Fatalf("encoding request: %v", err) + } + + et.host.Path = "retry_test" + resp, err := c.Post(et.host.String(), "application/json", buf) + if err != nil || resp.StatusCode != 200 { + et.Fatalf("creating retry test: err: %v, resp: %+v", err, resp) + } + defer func() { + closeErr := resp.Body.Close() + if err == nil { + err = closeErr + } + }() + testRes := struct { + TestID string `json:"id"` + }{} + if err := json.NewDecoder(resp.Body).Decode(&testRes); err != nil { + et.Fatalf("decoding test ID: %v", err) + } + + et.id = testRes.TestID + + // Create wrapped client which will send emulator instructions + et.host.Path = "" + client, err := wrappedClient(et.T, et.host.String(), et.id) + if err != nil { + et.Fatalf("creating wrapped client: %v", err) + } + et.wrappedClient = client +} + +// Verifies that all instructions for a given retry testID have been used up +func (et *emulatorTest) check() { + et.host.Path = strings.Join([]string{"retry_test", et.id}, "/") + c := http.DefaultClient + resp, err := c.Get(et.host.String()) + if err != nil || resp.StatusCode != 200 { + et.Errorf("getting retry test: err: %v, resp: %+v", err, resp) + } + defer func() { + closeErr := resp.Body.Close() + if err == nil { + err = closeErr + } + }() + testRes := struct { + Instructions map[string][]string + Completed bool + }{} + if err := json.NewDecoder(resp.Body).Decode(&testRes); err != nil { + et.Errorf("decoding response: %v", err) + } + if !testRes.Completed { + et.Errorf("test not completed; unused instructions: %+v", testRes.Instructions) + } +} + +// Deletes a retry test resource +func (et *emulatorTest) delete() { + et.host.Path = strings.Join([]string{"retry_test", et.id}, "/") + c := http.DefaultClient + req, err := http.NewRequest("DELETE", et.host.String(), nil) + if err != nil { + et.Errorf("creating request: %v", err) + } + resp, err := c.Do(req) + if err != nil || resp.StatusCode != 200 { + et.Errorf("deleting test: err: %v, resp: %+v", err, resp) + } +} + +// retryTestRoundTripper sends the retry test ID to the emulator with each request +type retryTestRoundTripper struct { + *testing.T + rt http.RoundTripper + testID string +} + +func (wt *retryTestRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { + r.Header.Set("x-retry-test-id", wt.testID) + + requestDump, err := httputil.DumpRequest(r, false) + if err != nil { + wt.Logf("error creating request dump: %v", err) + } + + resp, err := wt.rt.RoundTrip(r) + if err != nil { + wt.Logf("roundtrip error (may be expected): %v\nrequest: %s", err, requestDump) + } + return resp, err +} + +// Create custom client that sends instructions to the storage testbench Retry Test API +func wrappedClient(t *testing.T, host, testID string) (*Client, error) { + ctx := context.Background() + base := http.DefaultTransport + trans, err := htransport.NewTransport(ctx, base, option.WithScopes(raw.DevstorageFullControlScope), + option.WithUserAgent("custom-user-agent")) + if err != nil { + return nil, fmt.Errorf("failed to create http client: %v", err) + } + c := http.Client{Transport: trans} + + // Add RoundTripper to the created HTTP client + wrappedTrans := &retryTestRoundTripper{rt: c.Transport, testID: testID, T: t} + c.Transport = wrappedTrans + + // Supply this client to storage.NewClient + client, err := NewClient(ctx, option.WithHTTPClient(&c), option.WithEndpoint(host+"/storage/v1/")) + return client, err +}