@ -27,6 +27,7 @@
# include <google/protobuf/wrappers.pb.h>
# include "absl/status/status.h"
# include "absl/status/statusor.h"
# include "gmock/gmock.h"
# include "gtest/gtest.h"
# include "upb/def.hpp"
@ -39,6 +40,7 @@
# include "src/core/lib/config/core_configuration.h"
# include "src/core/lib/gprpp/orphanable.h"
# include "src/core/lib/gprpp/ref_counted_ptr.h"
# include "src/core/lib/gprpp/validation_errors.h"
# include "src/core/lib/load_balancing/lb_policy.h"
# include "src/core/lib/load_balancing/lb_policy_factory.h"
# include "src/core/lib/load_balancing/lb_policy_registry.h"
@ -47,10 +49,8 @@
# include "src/proto/grpc/testing/xds/v3/ring_hash.pb.h"
# include "src/proto/grpc/testing/xds/v3/round_robin.pb.h"
# include "src/proto/grpc/testing/xds/v3/typed_struct.pb.h"
# include "src/proto/grpc/testing/xds/v3/udpa_typed_struct.pb.h"
# include "src/proto/grpc/testing/xds/v3/wrr_locality.pb.h"
# include "test/core/util/test_config.h"
# include "test/cpp/util/config_grpc_cli.h"
namespace grpc_core {
namespace testing {
@ -66,7 +66,7 @@ using ::xds::type::v3::TypedStruct;
// Uses XdsLbPolicyRegistry to convert
// envoy::config::cluster::v3::LoadBalancingPolicy to gRPC's JSON form.
absl : : StatusOr < Json : : Array > ConvertXdsPolicy ( LoadBalancingPolicyProto policy ) {
absl : : StatusOr < std : : string > ConvertXdsPolicy ( LoadBalancingPolicyProto policy ) {
std : : string serialized_policy = policy . SerializeAsString ( ) ;
upb : : Arena arena ;
upb : : SymbolTable symtab ;
@ -75,117 +75,174 @@ absl::StatusOr<Json::Array> ConvertXdsPolicy(LoadBalancingPolicyProto policy) {
nullptr , symtab . ptr ( ) , arena . ptr ( ) } ;
auto * upb_policy = envoy_config_cluster_v3_LoadBalancingPolicy_parse (
serialized_policy . data ( ) , serialized_policy . size ( ) , arena . ptr ( ) ) ;
return XdsLbPolicyRegistry : : ConvertXdsLbPolicyConfig ( context , upb_policy ) ;
ValidationErrors errors ;
ValidationErrors : : ScopedField field ( & errors , " .load_balancing_policy " ) ;
auto config = XdsLbPolicyRegistry ( ) . ConvertXdsLbPolicyConfig (
context , upb_policy , & errors ) ;
if ( ! errors . ok ( ) ) return errors . status ( " validation errors " ) ;
EXPECT_EQ ( config . size ( ) , 1 ) ;
return Json { config [ 0 ] } . Dump ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , EmptyLoadBalancingPolicy ) {
auto result = ConvertXdsPolicy ( LoadBalancingPolicyProto ( ) ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_THAT (
std : : string ( result . status ( ) . message ( ) ) ,
: : testing : : HasSubstr ( " No supported load balancing policy config found " ) ) ;
}
// A gRPC LB policy factory for a custom policy. None of the methods
// will actually be used; we just need it to be present in the gRPC LB
// policy registry.
class CustomLbPolicyFactory : public LoadBalancingPolicyFactory {
public :
OrphanablePtr < LoadBalancingPolicy > CreateLoadBalancingPolicy (
LoadBalancingPolicy : : Args /*args*/ ) const override {
GPR_ASSERT ( false ) ;
return nullptr ;
}
TEST ( XdsLbPolicyRegistryTest , UnsupportedBuiltinType ) {
absl : : string_view name ( ) const override { return " test.CustomLb " ; }
absl : : StatusOr < RefCountedPtr < LoadBalancingPolicy : : Config > >
ParseLoadBalancingConfig ( const Json & /*json*/ ) const override {
return nullptr ;
}
} ;
//
// RoundRobin
//
TEST ( RoundRobin , Basic ) {
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
LoadBalancingPolicyProto ( ) ) ;
RoundRobin ( ) ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_THAT (
std : : string ( result . status ( ) . message ( ) ) ,
: : testing : : HasSubstr ( " No supported load balancing policy config found " ) ) ;
ASSERT_TRUE ( result . ok ( ) ) < < result . status ( ) ;
EXPECT_EQ ( * result , " { \" round_robin \" :{}} " ) ;
}
TEST ( XdsLbPolicyRegistryTest , MissingTypedExtensionConfig ) {
//
// RingHash
//
TEST ( RingHashConfig , DefaultConfig ) {
LoadBalancingPolicyProto policy ;
policy . add_policies ( ) ;
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( RingHash ( ) ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_THAT ( std : : string ( result . status ( ) . message ( ) ) ,
: : testing : : HasSubstr ( " Error parsing LoadBalancingPolicy::Policy "
" - Missing typed_extension_config field " ) ) ;
ASSERT_TRUE ( result . ok ( ) ) < < result . status ( ) ;
EXPECT_EQ ( * result ,
" { \" ring_hash_experimental \" :{ "
" \" maxRingSize \" :8388608, \" minRingSize \" :1024}} " ) ;
}
TEST ( XdsLbPolicyRegistryTest , MissingTypedConfig ) {
TEST ( RingHashConfig , FieldsExplicitlySet ) {
RingHash ring_hash ;
ring_hash . set_hash_function ( RingHash : : XX_HASH ) ;
ring_hash . mutable_minimum_ring_size ( ) - > set_value ( 1234 ) ;
ring_hash . mutable_maximum_ring_size ( ) - > set_value ( 4567 ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) ;
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( ring_hash ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_THAT (
std : : string ( result . status ( ) . message ( ) ) ,
: : testing : : HasSubstr ( " Error parsing LoadBalancingPolicy::Policy - "
" Missing TypedExtensionConfig::typed_config field " ) ) ;
ASSERT_TRUE ( result . ok ( ) ) < < result . status ( ) ;
EXPECT_EQ ( * result ,
" { \" ring_hash_experimental \" :{ "
" \" maxRingSize \" :4567, \" minRingSize \" :1234}} " ) ;
}
TEST ( XdsLbPolicyRegistryTest , RingHashInvalidHash ) {
TEST ( RingHashConfig , InvalidHashFunction ) {
RingHash ring_hash ;
ring_hash . set_hash_function ( RingHash : : DEFAULT_HASH ) ;
ring_hash . set_hash_function ( RingHash : : MURMUR_HASH_2 ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
ring_hash ) ;
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( ring_hash ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_THAT (
std : : string ( result . status ( ) . message ( ) ) ,
: : testing : : HasSubstr ( " Invalid hash function provided for RingHash "
" loadbalancing policy. Only XX_HASH is supported " ) ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" validation errors: [ "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config.value[envoy.extensions.load_balancing_policies "
" .ring_hash.v3.RingHash].hash_function "
" error:unsupported value (must be XX_HASH)] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , RingHashRingSizeDefaults ) {
TEST ( RingHashConfig , RingSizesTooHigh ) {
RingHash ring_hash ;
ring_hash . set_hash_function ( RingHash : : XX_HASH ) ;
ring_hash . mutable_minimum_ring_size ( ) - > set_value ( 8388609 ) ;
ring_hash . mutable_maximum_ring_size ( ) - > set_value ( 8388609 ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
ring_hash ) ;
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( ring_hash ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_TRUE ( result . ok ( ) ) ;
EXPECT_EQ ( result - > size ( ) , 1 ) ;
EXPECT_EQ ( ( * result ) [ 0 ] , Json : : Parse ( " { "
" \" ring_hash_experimental \" : { "
" }} " )
. value ( ) ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" validation errors: [ "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config.value[envoy.extensions.load_balancing_policies "
" .ring_hash.v3.RingHash].maximum_ring_size "
" error:value must be in the range [1, 8388608]; "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config.value[envoy.extensions.load_balancing_policies "
" .ring_hash.v3.RingHash].minimum_ring_size "
" error:value must be in the range [1, 8388608]] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , RingHashRingSizeCustom ) {
TEST ( RingHashConfig , RingSizesTooLow ) {
RingHash ring_hash ;
ring_hash . set_hash_function ( RingHash : : XX_HASH ) ;
ring_hash . mutable_minimum_ring_size ( ) - > set_value ( 1234 ) ;
ring_hash . mutable_maximum_ring_size ( ) - > set_value ( 4567 ) ;
ring_hash . mutable_minimum_ring_size ( ) - > set_value ( 0 ) ;
ring_hash . mutable_maximum_ring_size ( ) - > set_value ( 0 ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
ring_hash ) ;
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( ring_hash ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_TRUE ( result . ok ( ) ) ;
EXPECT_EQ ( result - > size ( ) , 1 ) ;
EXPECT_EQ ( ( * result ) [ 0 ] , Json : : Parse ( " { "
" \" ring_hash_experimental \" : { "
" \" minRingSize \" : 1234, "
" \" maxRingSize \" : 4567 "
" }} " )
. value ( ) ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" validation errors: [ "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config.value[envoy.extensions.load_balancing_policies "
" .ring_hash.v3.RingHash].maximum_ring_size "
" error:value must be in the range [1, 8388608]; "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config.value[envoy.extensions.load_balancing_policies "
" .ring_hash.v3.RingHash].minimum_ring_size "
" error:value must be in the range [1, 8388608]] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , RoundRobin ) {
TEST ( RingHashConfig , MinRingSizeGreaterThanMaxRingSize ) {
RingHash ring_hash ;
ring_hash . mutable_minimum_ring_size ( ) - > set_value ( 1000 ) ;
ring_hash . mutable_maximum_ring_size ( ) - > set_value ( 999 ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
RoundRobin ( ) ) ;
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( ring_hash ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_TRUE ( result . ok ( ) ) ;
EXPECT_EQ ( result - > size ( ) , 1 ) ;
EXPECT_EQ ( ( * result ) [ 0 ] , Json : : Parse ( " { "
" \" round_robin \" : {} "
" } " )
. value ( ) ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" validation errors: [ "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config.value[envoy.extensions.load_balancing_policies "
" .ring_hash.v3.RingHash].minimum_ring_size "
" error:cannot be greater than maximum_ring_size] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , WrrLocality ) {
//
// WrrLocality
//
TEST ( WrrLocality , RoundRobinChild ) {
WrrLocality wrr_locality ;
wrr_locality . mutable_endpoint_picking_policy ( )
- > add_policies ( )
@ -197,52 +254,78 @@ TEST(XdsLbPolicyRegistryTest, WrrLocality) {
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
wrr_locality ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_TRUE ( result . ok ( ) ) ;
EXPECT_EQ ( result - > size ( ) , 1 ) ;
EXPECT_EQ ( ( * result ) [ 0 ] , Json : : Parse ( " { "
" \" xds_wrr_locality_experimental \" : { "
" \" child_policy \" : [{ "
" \" round_robin \" : {} "
" }] "
" }} " )
. value ( ) ) ;
ASSERT_TRUE ( result . ok ( ) ) < < result . status ( ) ;
EXPECT_EQ ( * result ,
" { \" xds_wrr_locality_experimental \" :{ "
" \" childPolicy \" :[{ \" round_robin \" :{}}]}} " ) ;
}
TEST ( XdsLbPolicyRegistryTest , WrrLocality MissingEndpointPickingPolicy) {
TEST ( WrrLocality , MissingEndpointPickingPolicy ) {
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
WrrLocality ( ) ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_THAT ( std : : string ( result . status ( ) . message ( ) ) ,
: : testing : : ContainsRegex (
" Error parsing LoadBalancingPolicy.*WrrLocality: "
" endpoint_picking_policy not found " ) ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" validation errors: [ "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config.value[envoy.extensions.load_balancing_policies "
" .wrr_locality.v3.WrrLocality].endpoint_picking_policy "
" error:field not present] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , WrrLocalityChildPolicyError ) {
TEST ( WrrLocality , ChildPolicyInvalid ) {
RingHash ring_hash ;
ring_hash . set_hash_function ( RingHash : : MURMUR_HASH_2 ) ;
WrrLocality wrr_locality ;
wrr_locality . mutable_endpoint_picking_policy ( )
- > add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( RingHash ( ) ) ;
- > PackFrom ( ring_hash ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
wrr_locality ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_THAT ( std : : string ( result . status ( ) . message ( ) ) ,
: : testing : : ContainsRegex (
" Error parsing LoadBalancingPolicy.*Error parsing "
" WrrLocality load balancing policy.*Error parsing "
" LoadBalancingPolicy.*Invalid hash function provided for "
" RingHash loadbalancing policy. Only XX_HASH is supported. " ) ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" validation errors: [ "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config.value[envoy.extensions.load_balancing_policies "
" .wrr_locality.v3.WrrLocality].endpoint_picking_policy.policies[0] "
" .typed_extension_config.typed_config.value[ "
" envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash] "
" .hash_function "
" error:unsupported value (must be XX_HASH)] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , WrrLocalityUnsupportedTypeSkipped ) {
TEST ( WrrLocality , NoSupportedChildPolicy ) {
WrrLocality wrr_locality ;
wrr_locality . mutable_endpoint_picking_policy ( )
- > add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( LoadBalancingPolicyProto ( ) ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
wrr_locality ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" validation errors: [ "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config.value[envoy.extensions.load_balancing_policies "
" .wrr_locality.v3.WrrLocality].endpoint_picking_policy "
" error:no supported load balancing policy config found] " )
< < result . status ( ) ;
}
TEST ( WrrLocality , UnsupportedChildPolicyTypeSkipped ) {
// Create WrrLocality policy and add two policies to its list, an unsupported
// type and then a known RoundRobin type. Expect that the unsupported type is
// skipped and RoundRobin is selected.
@ -262,234 +345,130 @@ TEST(XdsLbPolicyRegistryTest, WrrLocalityUnsupportedTypeSkipped) {
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
wrr_locality ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_TRUE ( result . ok ( ) ) ;
EXPECT_EQ ( result - > size ( ) , 1 ) ;
EXPECT_EQ ( ( * result ) [ 0 ] , Json : : Parse ( " { "
" \" xds_wrr_locality_experimental \" : { "
" \" child_policy \" : [{ "
" \" round_robin \" : {} "
" }] "
" }} " )
. value ( ) ) ;
EXPECT_EQ ( * result ,
" { \" xds_wrr_locality_experimental \" :{ "
" \" childPolicy \" :[{ \" round_robin \" :{}}]}} " ) ;
}
class CustomLbPolicyFactory : public LoadBalancingPolicyFactory {
public :
OrphanablePtr < LoadBalancingPolicy > CreateLoadBalancingPolicy (
LoadBalancingPolicy : : Args /* args */ ) const override {
GPR_ASSERT ( false ) ;
return nullptr ;
}
absl : : string_view name ( ) const override { return " test.CustomLb " ; }
absl : : StatusOr < RefCountedPtr < LoadBalancingPolicy : : Config > >
ParseLoadBalancingConfig ( const Json & /*json*/ ) const override {
return nullptr ;
}
} ;
//
// CustomPolicy
//
TEST ( XdsLbPolicyRegistryTest , CustomLbPolicy ) {
TEST ( CustomPolicy , Basic ) {
TypedStruct typed_struct ;
typed_struct . set_type_url ( " type.googleapis.com/test.CustomLb " ) ;
auto * fields = typed_struct . mutable_value ( ) - > mutable_fields ( ) ;
( * fields ) [ " foo " ] . set_string_value ( " bar " ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
typed_struct ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_TRUE ( result . ok ( ) ) ;
EXPECT_EQ ( result - > size ( ) , 1 ) ;
EXPECT_EQ ( ( * result ) [ 0 ] , Json : : Parse ( " { \" test.CustomLb \" : {}} " ) . value ( ) ) ;
ASSERT_TRUE ( result . ok ( ) ) < < result . status ( ) ;
EXPECT_EQ ( * result , " { \" test.CustomLb \" :{ \" foo \" : \" bar \" }} " ) ;
}
TEST ( XdsLbPolicyRegistryTest , CustomLbPolicyUdpaTyped ) {
: : udpa : : type : : v1 : : TypedStruct typed_struct ;
typed_struct . set_type_url ( " type.googleapis.com/test.CustomLb " ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
typed_struct ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_TRUE ( result . ok ( ) ) ;
EXPECT_EQ ( result - > size ( ) , 1 ) ;
EXPECT_EQ ( ( * result ) [ 0 ] , Json : : Parse ( " { \" test.CustomLb \" : {}} " ) . value ( ) ) ;
}
//
// XdsLbPolicyRegistryTest
//
TEST ( XdsLbPolicyRegistryTest , UnsupportedCustomTypeError ) {
TypedStruct typed_struct ;
typed_struct . set_type_url ( " myorg/foo/bar/test.UnknownLb " ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
typed_struct ) ;
auto result = ConvertXdsPolicy ( policy ) ;
TEST ( XdsLbPolicyRegistryTest , EmptyLoadBalancingPolicy ) {
auto result = ConvertXdsPolicy ( LoadBalancingPolicyProto ( ) ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_THAT (
std : : string ( result . status ( ) . message ( ) ) ,
: : testing : : HasSubstr ( " No supported load balancing policy config found " ) ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" validation errors: [field:load_balancing_policy "
" error:no supported load balancing policy config found] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , CustomTypeInvalidUrlMissingSlash ) {
TypedStruct typed_struct ;
typed_struct . set_type_url ( " test.UnknownLb " ) ;
TEST ( XdsLbPolicyRegistryTest , MissingTypedExtensionConfig ) {
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
typed_struct ) ;
policy . add_policies ( ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" Error parsing "
" LoadBalancingPolicy::Policy::TypedExtensionConfig:: "
" typed_config: [ "
" field:value[xds.type.v3.TypedStruct].type_url "
" error:invalid value \" test.UnknownLb \" ] " )
" validation errors: [ "
" field:load_balancing_policy.policies[0].typed_extension_config "
" error:field not present] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , CustomTypeInvalidUrlEmptyType ) {
TypedStruct typed_struct ;
typed_struct . set_type_url ( " myorg/ " ) ;
TEST ( XdsLbPolicyRegistryTest , MissingTypedConfig ) {
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
typed_struct ) ;
policy . add_policies ( ) - > mutable_typed_extension_config ( ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" Error parsing "
" LoadBalancingPolicy::Policy::TypedExtensionConfig:: "
" typed_config: "
" [field:value[xds.type.v3.TypedStruct].type_url "
" error:invalid value \" myorg/ \" ] " )
" validation errors: [ "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config error:field not present] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , CustomLbPolicyJsonConversion ) {
// This tests that we pass along errors that are generated by
// ExtractXdsExtension(). An exhaustive list of error cases caught by
// ExtractXdsExtension() are covered in xds_common_types_test.
TEST ( XdsLbPolicyRegistryTest , ErrorExtractingExtension ) {
TypedStruct typed_struct ;
ASSERT_TRUE ( grpc : : protobuf : : TextFormat : : ParseFromString (
R " pb(
type_url : " type.googleapis.com/test.CustomLb "
value {
fields {
key : " key "
value { null_value : NULL_VALUE }
}
fields {
key : " number "
value { number_value : 123 }
}
fields {
key : " string "
value { string_value : " value " }
}
fields {
key : " struct "
value {
struct_value {
fields {
key : " key "
value { null_value : NULL_VALUE }
}
}
}
}
fields {
key : " list "
value {
list_value {
values { null_value : NULL_VALUE }
values { number_value : 234 }
}
}
}
}
) pb " ,
& typed_struct ) ) ;
typed_struct . set_type_url ( " type.googleapis.com/ " ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
typed_struct ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_TRUE ( result . ok ( ) ) ;
EXPECT_EQ ( result - > size ( ) , 1 ) ;
EXPECT_EQ ( ( * result ) [ 0 ] , Json : : Parse (
R " json({
" test.CustomLb " : {
" key " : null ,
" number " : 123 ,
" string " : " value " ,
" struct " : {
" key " : null
} ,
" list " : [ null , 234 ]
}
} ) json " )
. value ( ) ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" validation errors: [ "
" field:load_balancing_policy.policies[0].typed_extension_config "
" .typed_config.value[xds.type.v3.TypedStruct].type_url "
" error:invalid value \" type.googleapis.com/ \" ] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , CustomLbPolicyListError ) {
TypedStruct typed_struct ;
typed_struct . set_type_url ( " type.googleapis.com/test.CustomLb " ) ;
auto * fields = typed_struct . mutable_value ( ) - > mutable_fields ( ) ;
google : : protobuf : : Value value ;
value . mutable_list_value ( ) - > add_values ( ) ;
( * fields ) [ " key " ] = value ;
TEST ( XdsLbPolicyRegistryTest , NoSupportedType ) {
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
typed_struct ) ;
// Unsupported built-in type.
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( LoadBalancingPolicyProto ( ) ) ;
// Unsupported custom type.
TypedStruct typed_struct ;
typed_struct . set_type_url ( " myorg/foo/bar/test.UnknownLb " ) ;
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( typed_struct ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_EQ ( result . status ( ) . message ( ) ,
" Error parsing "
" LoadBalancingPolicy::Policy::TypedExtensionConfig::typed_config: [ "
" field:value[xds.type.v3.TypedStruct].value[test.CustomLb] "
" error:error encoding google::Protobuf::Struct as JSON: "
" No value set in Value proto] " )
" validation errors: [field:load_balancing_policy "
" error:no supported load balancing policy config found] " )
< < result . status ( ) ;
}
TEST ( XdsLbPolicyRegistryTest , UnsupportedBuiltInTypeSkipped ) {
// Add two policies to list, an unsupported type and then a known RoundRobin
// type. Expect that the unsupported type is skipped and RoundRobin is
// selected.
TEST ( XdsLbPolicyRegistryTest , UnsupportedTypesSkipped ) {
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
LoadBalancingPolicyProto ( ) ) ;
lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
RoundRobin ( ) ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_TRUE ( result . ok ( ) ) ;
EXPECT_EQ ( result - > size ( ) , 1 ) ;
EXPECT_EQ ( ( * result ) [ 0 ] , Json : : Parse ( " { "
" \" round_robin \" : {} "
" } " )
. value ( ) ) ;
}
TEST ( XdsLbPolicyRegistryTest , UnsupportedCustomTypeSkipped ) {
// Add two policies to list, an unsupported custom type and then a known
// RoundRobin type. Expect that the unsupported type is skipped and RoundRobin
// is selected.
// Unsupported built-in type.
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( LoadBalancingPolicyProto ( ) ) ;
// Unsupported custom type.
TypedStruct typed_struct ;
typed_struct . set_type_url ( " myorg/foo/bar/test.UnknownLb " ) ;
LoadBalancingPolicyProto policy ;
auto * lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
typed_struct ) ;
lb_policy = policy . add_policies ( ) ;
lb_policy - > mutable_typed_extension_config ( ) - > mutable_typed_config ( ) - > PackFrom (
RoundRobin ( ) ) ;
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( typed_struct ) ;
// Supported type.
policy . add_policies ( )
- > mutable_typed_extension_config ( )
- > mutable_typed_config ( )
- > PackFrom ( RoundRobin ( ) ) ;
auto result = ConvertXdsPolicy ( policy ) ;
EXPECT_TRUE ( result . ok ( ) ) ;
EXPECT_EQ ( result - > size ( ) , 1 ) ;
EXPECT_EQ ( ( * result ) [ 0 ] , Json : : Parse ( " { "
" \" round_robin \" : {} "
" } " )
. value ( ) ) ;
ASSERT_TRUE ( result . ok ( ) ) < < result . status ( ) ;
EXPECT_EQ ( * result , " { \" round_robin \" :{}} " ) ;
}
// Build a recurse load balancing policy that goes beyond the max allowable
@ -517,8 +496,7 @@ TEST(XdsLbPolicyRegistryTest, MaxRecursion) {
auto result = ConvertXdsPolicy ( BuildRecursiveLoadBalancingPolicy ( 0 ) ) ;
EXPECT_EQ ( result . status ( ) . code ( ) , absl : : StatusCode : : kInvalidArgument ) ;
EXPECT_THAT ( std : : string ( result . status ( ) . message ( ) ) ,
: : testing : : ContainsRegex ( " LoadBalancingPolicy configuration has "
" a recursion depth of more than 16 " ) ) ;
: : testing : : EndsWith ( " error:exceeded max recursion depth of 16] " ) ) ;
}
} // namespace
@ -533,7 +511,6 @@ int main(int argc, char** argv) {
builder - > lb_policy_registry ( ) - > RegisterLoadBalancingPolicyFactory (
std : : make_unique < grpc_core : : testing : : CustomLbPolicyFactory > ( ) ) ;
} ) ;
grpc_init ( ) ;
auto result = RUN_ALL_TESTS ( ) ;
grpc_shutdown ( ) ;