@@ -28,6 +28,7 @@ import (
2828 "testing"
2929 "time"
3030
31+ "github.com/google/go-cmp/cmp"
3132 "github.com/google/uuid"
3233 "google.golang.org/grpc"
3334 "google.golang.org/grpc/codes"
@@ -44,6 +45,7 @@ import (
4445 "google.golang.org/grpc/status"
4546 "google.golang.org/protobuf/types/known/durationpb"
4647 "google.golang.org/protobuf/types/known/wrapperspb"
48+ "google.golang.org/protobuf/testing/protocmp"
4749
4850 v3clusterpb "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
4951 v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
@@ -86,13 +88,12 @@ func (s) TestConfigUpdateWithSameLoadReportingServerConfig(t *testing.T) {
8688 testutils .CreateBootstrapFileForTesting (t , bc )
8789
8890 // Create an xDS resolver with the above bootstrap configuration.
89- var resolverBuilder resolver.Builder
90- var err error
91- if newResolver := internal .NewXDSResolverWithConfigForTesting ; newResolver != nil {
92- resolverBuilder , err = newResolver .(func ([]byte ) (resolver.Builder , error ))(bc )
93- if err != nil {
94- t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
95- }
91+ if internal .NewXDSResolverWithConfigForTesting == nil {
92+ t .Fatalf ("internal.NewXDSResolverWithConfigForTesting is nil" )
93+ }
94+ resolverBuilder , err := internal .NewXDSResolverWithConfigForTesting .(func ([]byte ) (resolver.Builder , error ))(bc )
95+ if err != nil {
96+ t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
9697 }
9798
9899 // Start a server backend exposing the test service.
@@ -195,13 +196,12 @@ func (s) TestLoadReportingPickFirstMultiLocality(t *testing.T) {
195196 bc := e2e .DefaultBootstrapContents (t , nodeID , mgmtServer .Address )
196197
197198 // Create an xDS resolver with the above bootstrap configuration.
198- var resolverBuilder resolver.Builder
199- var err error
200- if newResolver := internal .NewXDSResolverWithConfigForTesting ; newResolver != nil {
201- resolverBuilder , err = newResolver .(func ([]byte ) (resolver.Builder , error ))(bc )
202- if err != nil {
203- t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
204- }
199+ if internal .NewXDSResolverWithConfigForTesting == nil {
200+ t .Fatalf ("internal.NewXDSResolverWithConfigForTesting is nil" )
201+ }
202+ resolverBuilder , err := internal .NewXDSResolverWithConfigForTesting .(func ([]byte ) (resolver.Builder , error ))(bc )
203+ if err != nil {
204+ t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
205205 }
206206
207207 // Start two server backends exposing the test service.
@@ -360,8 +360,8 @@ func waitForSuccessfulLoadReport(ctx context.Context, lrsServer *fakeserver.Serv
360360}
361361
362362// Tests that circuit breaking limits RPCs E2E.
363- func TestCircuitBreaking (t * testing.T ) {
364- // Create an xDS management server that serves ADS requests.
363+ func ( s ) TestCircuitBreaking (t * testing.T ) {
364+ // Create an xDS management server that serves ADS and LRS requests.
365365 mgmtServer := e2e .StartManagementServer (t , e2e.ManagementServerOptions {SupportLoadReportingService : true })
366366
367367 // Create bootstrap configuration pointing to the above management server.
@@ -370,13 +370,12 @@ func TestCircuitBreaking(t *testing.T) {
370370 testutils .CreateBootstrapFileForTesting (t , bc )
371371
372372 // Create an xDS resolver with the above bootstrap configuration.
373- var resolverBuilder resolver.Builder
374- var err error
375- if newResolver := internal .NewXDSResolverWithConfigForTesting ; newResolver != nil {
376- resolverBuilder , err = newResolver .(func ([]byte ) (resolver.Builder , error ))(bc )
377- if err != nil {
378- t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
379- }
373+ if internal .NewXDSResolverWithConfigForTesting == nil {
374+ t .Fatalf ("internal.NewXDSResolverWithConfigForTesting is nil" )
375+ }
376+ resolverBuilder , err := internal .NewXDSResolverWithConfigForTesting .(func ([]byte ) (resolver.Builder , error ))(bc )
377+ if err != nil {
378+ t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
380379 }
381380
382381 // Start a server backend exposing the test service.
@@ -392,15 +391,15 @@ func TestCircuitBreaking(t *testing.T) {
392391 server := stubserver .StartTestService (t , f )
393392 defer server .Stop ()
394393
395- // Configure the xDS management server with default resources.
394+ // Configure xDS resources on the management server with a circuit breaking
395+ // policy that limits the maximum number of concurrent requests to 3.
396396 const serviceName = "my-test-xds-service"
397397 const maxRequests = 3
398398 resources := e2e .DefaultClientResources (e2e.ResourceParams {
399399 DialTarget : serviceName ,
400400 NodeID : nodeID ,
401401 Host : "localhost" ,
402402 Port : testutils .ParsePort (t , server .Address ),
403- SecLevel : e2e .SecurityLevelNone ,
404403 })
405404 resources .Clusters [0 ].CircuitBreakers = & v3clusterpb.CircuitBreakers {
406405 Thresholds : []* v3clusterpb.CircuitBreakers_Thresholds {
@@ -429,6 +428,7 @@ func TestCircuitBreaking(t *testing.T) {
429428 }
430429 defer cc .Close ()
431430
431+ cc .Connect ()
432432 client := testgrpc .NewTestServiceClient (cc )
433433
434434 // Start maxRequests streams.
@@ -442,6 +442,9 @@ func TestCircuitBreaking(t *testing.T) {
442442 // allowed due to inherent raciness in the tracking, however.
443443 const droppedRPCCount = 100
444444 for i := 0 ; i < droppedRPCCount ; i ++ {
445+ if ctx .Err () != nil {
446+ t .Fatalf ("Context error: %v" , ctx .Err ())
447+ }
445448 _ , err := client .FullDuplexCall (ctx )
446449 switch {
447450 case err == nil :
@@ -451,7 +454,6 @@ func TestCircuitBreaking(t *testing.T) {
451454 default :
452455 t .Errorf ("client.FullDuplexCall(_) failed with unexpected error = %v" , err )
453456 }
454- time .Sleep (10 * time .Millisecond )
455457 }
456458
457459 if _ , err = mgmtServer .LRSServer .LRSStreamOpenChan .Receive (ctx ); err != nil {
@@ -462,27 +464,37 @@ func TestCircuitBreaking(t *testing.T) {
462464 t .Fatalf ("Failure waiting for initial LRS request: %v" , err )
463465 }
464466
465- resp := fakeserver.Response {
467+ mgmtServer . LRSServer . LRSResponseChan <- & fakeserver.Response {
466468 Resp : & v3lrspb.LoadStatsResponse {
467469 SendAllClusters : true ,
468470 LoadReportingInterval : durationpb .New (10 * time .Millisecond ),
469471 },
470472 }
471- mgmtServer .LRSServer .LRSResponseChan <- & resp
472473
473474 select {
474475 case req := <- mgmtServer .LRSServer .LRSRequestChan .C :
475- loadStats := req .(* fakeserver.Request ).Req .(* v3lrspb.LoadStatsRequest )
476- for _ , cs := range loadStats .ClusterStats {
477- if cs .TotalDroppedRequests != droppedRPCCount {
478- t .Errorf ("Failed with unexpected diff got: %v, want: %v" , cs .TotalDroppedRequests , droppedRPCCount )
479- }
480- if cs .UpstreamLocalityStats [0 ].TotalIssuedRequests != maxRequests {
481- t .Errorf ("Failed with unexpected diff got: %v, want: %v" , cs .UpstreamLocalityStats [0 ].TotalIssuedRequests , maxRequests )
482- }
476+ clusterStats := req .(* fakeserver.Request ).Req .(* v3lrspb.LoadStatsRequest ).ClusterStats
477+ if l := len (clusterStats ); l != 1 {
478+ t .Fatalf ("Received load for %d clusters, want 1" , l )
479+ }
480+ clusterStats [0 ].LoadReportInterval = nil
481+ wantLoad := & v3endpointpb.ClusterStats {
482+ ClusterName : "cluster-my-test-xds-service" ,
483+ ClusterServiceName : "endpoints-my-test-xds-service" ,
484+ UpstreamLocalityStats : []* v3endpointpb.UpstreamLocalityStats {
485+ {
486+ Locality : & v3corepb.Locality {Region : "region-1" , Zone : "zone-1" , SubZone : "subzone-1" },
487+ TotalIssuedRequests : maxRequests ,
488+ TotalRequestsInProgress : maxRequests ,
489+ },
490+ },
491+ TotalDroppedRequests : droppedRPCCount ,
492+ }
493+ if diff := cmp .Diff (wantLoad , clusterStats [0 ], protocmp .Transform ()); diff != "" {
494+ t .Errorf ("Failed with unexpected diff (-want +got):\n %s" , diff )
483495 }
484496 case <- ctx .Done ():
485- t .Fatalf ("Timeout while waiting for LRS stream: %v" , ctx .Err ())
497+ t .Fatalf ("Timeout while waiting for load report on LRS stream: %v" , ctx .Err ())
486498 }
487499}
488500
@@ -493,16 +505,15 @@ func TestCircuitBreaking(t *testing.T) {
493505// distribution. The function aims to find a number of RPCs such that
494506// the observed probability is within a certain error_tolerance of the expected
495507// probability (p).
496- func computeIdealNumRpcs (p float64 , errorTolerance float64 ) uint64 {
497- numRpcs :=
498- uint64 (math .Ceil (p * (1 - p ) * 5.00 * 5.00 / errorTolerance / errorTolerance ))
508+ func computeIdealNumRpcs (p , errorTolerance float64 ) uint64 {
509+ numRpcs := uint64 (math .Ceil (p * (1 - p ) * 5.00 * 5.00 / errorTolerance / errorTolerance ))
499510 return numRpcs
500511}
501512
502513// TestDropByCategory verifies that the balancer correctly drops the picks, and
503514// that the drops are reported.
504- func TestDropByCategory (t * testing.T ) {
505- // Create an xDS management server that serves ADS requests.
515+ func ( s ) TestDropByCategory (t * testing.T ) {
516+ // Create an xDS management server that serves ADS and LRS requests.
506517 mgmtServer := e2e .StartManagementServer (t , e2e.ManagementServerOptions {SupportLoadReportingService : true })
507518
508519 // Create bootstrap configuration pointing to the above management server.
@@ -511,13 +522,12 @@ func TestDropByCategory(t *testing.T) {
511522 testutils .CreateBootstrapFileForTesting (t , bc )
512523
513524 // Create an xDS resolver with the above bootstrap configuration.
514- var resolverBuilder resolver.Builder
515- var err error
516- if newResolver := internal .NewXDSResolverWithConfigForTesting ; newResolver != nil {
517- resolverBuilder , err = newResolver .(func ([]byte ) (resolver.Builder , error ))(bc )
518- if err != nil {
519- t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
520- }
525+ if internal .NewXDSResolverWithConfigForTesting == nil {
526+ t .Fatalf ("internal.NewXDSResolverWithConfigForTesting is nil" )
527+ }
528+ resolverBuilder , err := internal .NewXDSResolverWithConfigForTesting .(func ([]byte ) (resolver.Builder , error ))(bc )
529+ if err != nil {
530+ t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
521531 }
522532
523533 // Start a server backend exposing the test service.
@@ -533,23 +543,24 @@ func TestDropByCategory(t *testing.T) {
533543 server := stubserver .StartTestService (t , f )
534544 defer server .Stop ()
535545
536- // Configure the xDS management server with default resources.
546+ // Configure xDS resources on the management server with drops configuration
547+ // that drops one RPC for every 50 RPCs made.
537548 const (
538549 dropReason = "test-dropping-category"
539550 dropNumerator = 1
540551 dropDenominator = 50
541552 serviceName = "my-test-xds-service"
542- errortolerance = 0.05
553+ errorTolerance = 0.05
543554 )
544- rpcDropRate := float64 (dropNumerator ) / float64 (dropDenominator )
545- rpcCount := computeIdealNumRpcs (rpcDropRate , errortolerance )
555+ wantRPCDropRate := float64 (dropNumerator ) / float64 (dropDenominator )
556+ rpcCount := computeIdealNumRpcs (wantRPCDropRate , errorTolerance )
557+ t .Logf ("Computed rpcCount: %d" , rpcCount )
546558
547559 resources := e2e .DefaultClientResources (e2e.ResourceParams {
548560 DialTarget : serviceName ,
549561 NodeID : nodeID ,
550562 Host : "localhost" ,
551563 Port : testutils .ParsePort (t , server .Address ),
552- SecLevel : e2e .SecurityLevelNone ,
553564 })
554565 resources .Clusters [0 ].LrsServer = & v3corepb.ConfigSource {
555566 ConfigSourceSpecifier : & v3corepb.ConfigSource_Self {
@@ -582,9 +593,10 @@ func TestDropByCategory(t *testing.T) {
582593 if err != nil {
583594 t .Fatalf ("failed to dial local test server: %v" , err )
584595 }
585- cc .Connect ()
586596 defer cc .Close ()
587597
598+ // Ensure the gRPC channel is READY before issuing RPCs to get accurate drop count.
599+ cc .Connect ()
588600 client := testgrpc .NewTestServiceClient (cc )
589601 testutils .AwaitState (ctx , t , cc , connectivity .Ready )
590602
@@ -615,24 +627,34 @@ func TestDropByCategory(t *testing.T) {
615627 resp := fakeserver.Response {
616628 Resp : & v3lrspb.LoadStatsResponse {
617629 SendAllClusters : true ,
618- LoadReportingInterval : durationpb .New (10 * time .Millisecond ),
630+ LoadReportingInterval : durationpb .New (time .Second ),
619631 },
620632 }
621633 mgmtServer .LRSServer .LRSResponseChan <- & resp
622634
635+ time .Sleep (time .Second )
623636 select {
624637 case req := <- mgmtServer .LRSServer .LRSRequestChan .C :
625638 loadStats := req .(* fakeserver.Request ).Req .(* v3lrspb.LoadStatsRequest )
626639 for _ , cs := range loadStats .ClusterStats {
627- dropRate := float64 (cs .TotalDroppedRequests / rpcCount )
628- if math .Abs (dropRate - rpcDropRate ) > errortolerance {
629- t .Errorf ("Drop rate goes out of errortolerance got %v, want %v" , math .Abs (dropRate - rpcDropRate ), errortolerance )
640+ if len (cs .DroppedRequests ) > 0 {
641+ if cs .DroppedRequests [0 ].Category != dropReason {
642+ t .Errorf ("Unexpected drop category got: %q, want: %q" , cs .DroppedRequests [0 ].Category , dropReason )
643+ }
644+ gotRPCDropRate := float64 (cs .DroppedRequests [0 ].DroppedCount ) / float64 (rpcCount )
645+ if math .Abs (gotRPCDropRate - wantRPCDropRate ) > errorTolerance {
646+ t .Errorf ("Drop rate goes out of errortolerance got: %v, want: %v, totalDroppedRequest: %v, totalIssuesRequest: %v" , math .Abs (gotRPCDropRate - wantRPCDropRate ), errorTolerance , cs .TotalDroppedRequests , cs .UpstreamLocalityStats [0 ].TotalIssuedRequests )
647+ }
648+ } else {
649+ t .Errorf ("No DroppedRequests reported, want at least one with category %q" , dropReason )
630650 }
631651 }
632652 case <- ctx .Done ():
633- t .Fatalf ("Timeout while waiting for LRS stream: %v" , ctx .Err ())
653+ t .Fatalf ("Timeout while waiting for load report on LRS stream: %v" , ctx .Err ())
634654 }
635655
656+ // Update the drop configuration to drop 1 out of every 40 RPCs,
657+ // and verify that the observed drop rate matches this new config.
636658 const (
637659 dropReason2 = "test-dropping-category-2"
638660 dropNumerator2 = 1
@@ -650,16 +672,17 @@ func TestDropByCategory(t *testing.T) {
650672 },
651673 },
652674 DropPercents : map [string ]int {
653- dropReason2 : dropNumerator2 * 100 / dropDenominator2 ,
675+ dropReason2 : dropNumerator2 * 100 / dropDenominator2 , // drops one RPC for every 40 RPCs made
654676 },
655677 })}
656678
657679 if err := mgmtServer .Update (ctx , resources ); err != nil {
658680 t .Fatal (err )
659681 }
660682
661- rpcDropRate = float64 (dropNumerator2 ) / float64 (dropDenominator2 )
662- rpcCount = computeIdealNumRpcs (rpcDropRate , errortolerance )
683+ wantRPCDropRate = float64 (dropNumerator2 ) / float64 (dropDenominator2 )
684+ rpcCount = computeIdealNumRpcs (wantRPCDropRate , errorTolerance )
685+ t .Logf ("Computed rpcCount: %d" , rpcCount )
663686
664687 for i := 0 ; i < int (rpcCount ); i ++ {
665688 if ctx .Err () != nil {
@@ -677,17 +700,28 @@ func TestDropByCategory(t *testing.T) {
677700 }
678701 }
679702
703+ time .Sleep (time .Second )
680704 select {
681705 case req := <- mgmtServer .LRSServer .LRSRequestChan .C :
682706 loadStats := req .(* fakeserver.Request ).Req .(* v3lrspb.LoadStatsRequest )
683707 for _ , cs := range loadStats .ClusterStats {
684- dropRate := float64 (cs .TotalDroppedRequests / rpcCount )
685- if math .Abs (dropRate - rpcDropRate ) > errortolerance {
686- t .Errorf ("Drop rate goes out of errortolerance got %v, want %v" , math .Abs (dropRate - rpcDropRate ), errortolerance )
708+ found := false
709+ for _ , dr := range cs .DroppedRequests {
710+ if dr .Category == dropReason2 {
711+ found = true
712+ gotRPCDropRate := float64 (dr .DroppedCount ) / float64 (rpcCount )
713+ if math .Abs (gotRPCDropRate - wantRPCDropRate ) > errorTolerance {
714+ t .Errorf ("Drop rate goes out of errortolerance got: %v, want: %v, totalDroppedRequest: %v, totalIssuesRequest: %v" , math .Abs (gotRPCDropRate - wantRPCDropRate ), errorTolerance , cs .TotalDroppedRequests , cs .UpstreamLocalityStats [0 ].TotalIssuedRequests )
715+ }
716+ break
717+ }
718+ }
719+ if ! found {
720+ t .Errorf ("No DroppedRequests reported for expected category %q" , dropReason2 )
687721 }
688722 }
689723 case <- ctx .Done ():
690- t .Fatalf ("Timeout while waiting for LRS stream: %v" , ctx .Err ())
724+ t .Fatalf ("Timeout while waiting for load report on LRS stream: %v" , ctx .Err ())
691725 }
692726}
693727
@@ -702,13 +736,12 @@ func (s) TestCircuitBreakingLogicalDNS(t *testing.T) {
702736 testutils .CreateBootstrapFileForTesting (t , bc )
703737
704738 // Create an xDS resolver with the above bootstrap configuration.
705- var resolverBuilder resolver.Builder
706- var err error
707- if newResolver := internal .NewXDSResolverWithConfigForTesting ; newResolver != nil {
708- resolverBuilder , err = newResolver .(func ([]byte ) (resolver.Builder , error ))(bc )
709- if err != nil {
710- t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
711- }
739+ if internal .NewXDSResolverWithConfigForTesting == nil {
740+ t .Fatalf ("internal.NewXDSResolverWithConfigForTesting is nil" )
741+ }
742+ resolverBuilder , err := internal .NewXDSResolverWithConfigForTesting .(func ([]byte ) (resolver.Builder , error ))(bc )
743+ if err != nil {
744+ t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
712745 }
713746
714747 // Start a server backend exposing the test service.
@@ -822,13 +855,12 @@ func (s) TestLRSLogicalDNS(t *testing.T) {
822855 testutils .CreateBootstrapFileForTesting (t , bc )
823856
824857 // Create an xDS resolver with the above bootstrap configuration.
825- var resolverBuilder resolver.Builder
826- var err error
827- if newResolver := internal .NewXDSResolverWithConfigForTesting ; newResolver != nil {
828- resolverBuilder , err = newResolver .(func ([]byte ) (resolver.Builder , error ))(bc )
829- if err != nil {
830- t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
831- }
858+ if internal .NewXDSResolverWithConfigForTesting == nil {
859+ t .Fatalf ("internal.NewXDSResolverWithConfigForTesting is nil" )
860+ }
861+ resolverBuilder , err := internal .NewXDSResolverWithConfigForTesting .(func ([]byte ) (resolver.Builder , error ))(bc )
862+ if err != nil {
863+ t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
832864 }
833865
834866 // Start a server backend exposing the test service.
0 commit comments