@@ -23,7 +23,6 @@ import (
23
23
"encoding/json"
24
24
"errors"
25
25
"fmt"
26
- "sort"
27
26
"strings"
28
27
"sync"
29
28
"testing"
@@ -64,7 +63,6 @@ const (
64
63
65
64
var (
66
65
testBackendEndpoints = []resolver.Endpoint {{Addresses : []resolver.Address {{Addr : "1.1.1.1:1" }}}}
67
- cmpOpts = cmp.Options {cmpopts .EquateEmpty (), cmp .AllowUnexported (loadData {}, localityData {}, requestData {}, serverLoadData {}), sortDataSlice }
68
66
toleranceCmpOpt = cmp.Options {cmpopts .EquateApprox (0 , 1e-5 ), cmp .AllowUnexported (loadData {}, localityData {}, requestData {}, serverLoadData {})}
69
67
)
70
68
@@ -279,345 +277,6 @@ func init() {
279
277
NewRandomWRR = testutils .NewTestWRR
280
278
}
281
279
282
- var sortDataSlice = cmp .Transformer ("SortDataSlice" , func (in []* loadData ) []* loadData {
283
- out := append ([]* loadData (nil ), in ... ) // Copy input to avoid mutating it
284
- sort .Slice (out ,
285
- func (i , j int ) bool {
286
- if out [i ].cluster < out [j ].cluster {
287
- return true
288
- }
289
- if out [i ].cluster == out [j ].cluster {
290
- return out [i ].service < out [j ].service
291
- }
292
- return false
293
- },
294
- )
295
- return out
296
- })
297
-
298
- func verifyLoadStoreData (wantStoreData , gotStoreData * loadData ) error {
299
- if diff := cmp .Diff (wantStoreData , gotStoreData , cmpOpts ); diff != "" {
300
- return fmt .Errorf ("store.stats() returned unexpected diff (-want +got):\n %s" , diff )
301
- }
302
- return nil
303
- }
304
-
305
- // TestDropByCategory verifies that the balancer correctly drops the picks, and
306
- // that the drops are reported.
307
- func (s ) TestDropByCategory (t * testing.T ) {
308
- ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
309
- defer cancel ()
310
-
311
- defer xdsclient .ClearCounterForTesting (testClusterName , testServiceName )
312
- xdsC := fakeclient .NewClient ()
313
-
314
- builder := balancer .Get (Name )
315
- cc := testutils .NewBalancerClientConn (t )
316
- b := builder .Build (cc , balancer.BuildOptions {})
317
- defer b .Close ()
318
-
319
- const (
320
- dropReason = "test-dropping-category"
321
- dropNumerator = 1
322
- dropDenominator = 2
323
- )
324
- testLRSServerConfig , err := bootstrap .ServerConfigForTesting (bootstrap.ServerConfigTestingOptions {
325
- URI : "trafficdirector.googleapis.com:443" ,
326
- ChannelCreds : []bootstrap.ChannelCreds {{Type : "google_default" }},
327
- })
328
- if err != nil {
329
- t .Fatalf ("Failed to create LRS server config for testing: %v" , err )
330
- }
331
- if err := b .UpdateClientConnState (balancer.ClientConnState {
332
- ResolverState : xdsclient .SetClient (resolver.State {Endpoints : testBackendEndpoints }, xdsC ),
333
- BalancerConfig : & LBConfig {
334
- Cluster : testClusterName ,
335
- EDSServiceName : testServiceName ,
336
- LoadReportingServer : testLRSServerConfig ,
337
- DropCategories : []DropConfig {{
338
- Category : dropReason ,
339
- RequestsPerMillion : million * dropNumerator / dropDenominator ,
340
- }},
341
- ChildPolicy : & internalserviceconfig.BalancerConfig {
342
- Name : roundrobin .Name ,
343
- },
344
- },
345
- }); err != nil {
346
- t .Fatalf ("unexpected error from UpdateClientConnState: %v" , err )
347
- }
348
-
349
- got , err := xdsC .WaitForReportLoad (ctx )
350
- if err != nil {
351
- t .Fatalf ("xdsClient.ReportLoad failed with error: %v" , err )
352
- }
353
- if got .Server != testLRSServerConfig {
354
- t .Fatalf ("xdsClient.ReportLoad called with {%q}: want {%q}" , got .Server , testLRSServerConfig )
355
- }
356
-
357
- sc1 := <- cc .NewSubConnCh
358
- sc1 .UpdateState (balancer.SubConnState {ConnectivityState : connectivity .Connecting })
359
- // This should get the connecting picker.
360
- if err := cc .WaitForPickerWithErr (ctx , balancer .ErrNoSubConnAvailable ); err != nil {
361
- t .Fatal (err .Error ())
362
- }
363
-
364
- sc1 .UpdateState (balancer.SubConnState {ConnectivityState : connectivity .Ready })
365
- // Test pick with one backend.
366
-
367
- testClusterLoadReporter := & testLoadReporter {cluster : testClusterName , service : testServiceName , drops : make (map [string ]uint64 ), localityRPCCount : make (map [clients.Locality ]* rpcCountData )}
368
-
369
- const rpcCount = 24
370
- if err := cc .WaitForPicker (ctx , func (p balancer.Picker ) error {
371
- // Override the loadStore in the picker with testClusterLoadReporter.
372
- picker := p .(* picker )
373
- originalLoadStore := picker .loadStore
374
- picker .loadStore = testClusterLoadReporter
375
- defer func () { picker .loadStore = originalLoadStore }()
376
-
377
- for i := 0 ; i < rpcCount ; i ++ {
378
- gotSCSt , err := p .Pick (balancer.PickInfo {})
379
- // Even RPCs are dropped.
380
- if i % 2 == 0 {
381
- if err == nil || ! strings .Contains (err .Error (), "dropped" ) {
382
- return fmt .Errorf ("pick.Pick, got %v, %v, want error RPC dropped" , gotSCSt , err )
383
- }
384
- continue
385
- }
386
- if err != nil || gotSCSt .SubConn != sc1 {
387
- return fmt .Errorf ("picker.Pick, got %v, %v, want SubConn=%v" , gotSCSt , err , sc1 )
388
- }
389
- if gotSCSt .Done == nil {
390
- continue
391
- }
392
- // Fail 1/4th of the requests that are not dropped.
393
- if i % 8 == 1 {
394
- gotSCSt .Done (balancer.DoneInfo {Err : fmt .Errorf ("test error" )})
395
- } else {
396
- gotSCSt .Done (balancer.DoneInfo {})
397
- }
398
- }
399
- return nil
400
- }); err != nil {
401
- t .Fatal (err .Error ())
402
- }
403
-
404
- // Dump load data from the store and compare with expected counts.
405
- const dropCount = rpcCount * dropNumerator / dropDenominator
406
- wantStatsData0 := & loadData {
407
- cluster : testClusterName ,
408
- service : testServiceName ,
409
- totalDrops : dropCount ,
410
- drops : map [string ]uint64 {dropReason : dropCount },
411
- localityStats : map [clients.Locality ]localityData {
412
- {}: {requestStats : requestData {
413
- succeeded : (rpcCount - dropCount ) * 3 / 4 ,
414
- errored : (rpcCount - dropCount ) / 4 ,
415
- issued : rpcCount - dropCount ,
416
- }},
417
- },
418
- }
419
-
420
- gotStatsData0 := testClusterLoadReporter .stats ()
421
- if err := verifyLoadStoreData (wantStatsData0 , gotStatsData0 ); err != nil {
422
- t .Fatal (err )
423
- }
424
-
425
- // Send an update with new drop configs.
426
- const (
427
- dropReason2 = "test-dropping-category-2"
428
- dropNumerator2 = 1
429
- dropDenominator2 = 4
430
- )
431
- if err := b .UpdateClientConnState (balancer.ClientConnState {
432
- ResolverState : xdsclient .SetClient (resolver.State {Endpoints : testBackendEndpoints }, xdsC ),
433
- BalancerConfig : & LBConfig {
434
- Cluster : testClusterName ,
435
- EDSServiceName : testServiceName ,
436
- LoadReportingServer : testLRSServerConfig ,
437
- DropCategories : []DropConfig {{
438
- Category : dropReason2 ,
439
- RequestsPerMillion : million * dropNumerator2 / dropDenominator2 ,
440
- }},
441
- ChildPolicy : & internalserviceconfig.BalancerConfig {
442
- Name : roundrobin .Name ,
443
- },
444
- },
445
- }); err != nil {
446
- t .Fatalf ("unexpected error from UpdateClientConnState: %v" , err )
447
- }
448
-
449
- if err := cc .WaitForPicker (ctx , func (p balancer.Picker ) error {
450
- // Override the loadStore in the picker with testClusterLoadReporter.
451
- picker := p .(* picker )
452
- originalLoadStore := picker .loadStore
453
- picker .loadStore = testClusterLoadReporter
454
- defer func () { picker .loadStore = originalLoadStore }()
455
- for i := 0 ; i < rpcCount ; i ++ {
456
- gotSCSt , err := p .Pick (balancer.PickInfo {})
457
- // Even RPCs are dropped.
458
- if i % 4 == 0 {
459
- if err == nil || ! strings .Contains (err .Error (), "dropped" ) {
460
- return fmt .Errorf ("pick.Pick, got %v, %v, want error RPC dropped" , gotSCSt , err )
461
- }
462
- continue
463
- }
464
- if err != nil || gotSCSt .SubConn != sc1 {
465
- return fmt .Errorf ("picker.Pick, got %v, %v, want SubConn=%v" , gotSCSt , err , sc1 )
466
- }
467
- if gotSCSt .Done != nil {
468
- gotSCSt .Done (balancer.DoneInfo {})
469
- }
470
- }
471
- return nil
472
- }); err != nil {
473
- t .Fatal (err .Error ())
474
- }
475
-
476
- const dropCount2 = rpcCount * dropNumerator2 / dropDenominator2
477
- wantStatsData1 := & loadData {
478
- cluster : testClusterName ,
479
- service : testServiceName ,
480
- totalDrops : dropCount2 ,
481
- drops : map [string ]uint64 {dropReason2 : dropCount2 },
482
- localityStats : map [clients.Locality ]localityData {
483
- {}: {requestStats : requestData {
484
- succeeded : rpcCount - dropCount2 ,
485
- issued : rpcCount - dropCount2 ,
486
- }},
487
- },
488
- }
489
-
490
- gotStatsData1 := testClusterLoadReporter .stats ()
491
- if err := verifyLoadStoreData (wantStatsData1 , gotStatsData1 ); err != nil {
492
- t .Fatal (err )
493
- }
494
- }
495
-
496
- // TestDropCircuitBreaking verifies that the balancer correctly drops the picks
497
- // due to circuit breaking, and that the drops are reported.
498
- func (s ) TestDropCircuitBreaking (t * testing.T ) {
499
- defer xdsclient .ClearCounterForTesting (testClusterName , testServiceName )
500
- xdsC := fakeclient .NewClient ()
501
-
502
- builder := balancer .Get (Name )
503
- cc := testutils .NewBalancerClientConn (t )
504
- b := builder .Build (cc , balancer.BuildOptions {})
505
- defer b .Close ()
506
-
507
- var maxRequest uint32 = 50
508
- testLRSServerConfig , err := bootstrap .ServerConfigForTesting (bootstrap.ServerConfigTestingOptions {
509
- URI : "trafficdirector.googleapis.com:443" ,
510
- ChannelCreds : []bootstrap.ChannelCreds {{Type : "google_default" }},
511
- })
512
- if err != nil {
513
- t .Fatalf ("Failed to create LRS server config for testing: %v" , err )
514
- }
515
- if err := b .UpdateClientConnState (balancer.ClientConnState {
516
- ResolverState : xdsclient .SetClient (resolver.State {Endpoints : testBackendEndpoints }, xdsC ),
517
- BalancerConfig : & LBConfig {
518
- Cluster : testClusterName ,
519
- EDSServiceName : testServiceName ,
520
- LoadReportingServer : testLRSServerConfig ,
521
- MaxConcurrentRequests : & maxRequest ,
522
- ChildPolicy : & internalserviceconfig.BalancerConfig {
523
- Name : roundrobin .Name ,
524
- },
525
- },
526
- }); err != nil {
527
- t .Fatalf ("unexpected error from UpdateClientConnState: %v" , err )
528
- }
529
-
530
- ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
531
- defer cancel ()
532
-
533
- got , err := xdsC .WaitForReportLoad (ctx )
534
- if err != nil {
535
- t .Fatalf ("xdsClient.ReportLoad failed with error: %v" , err )
536
- }
537
- if got .Server != testLRSServerConfig {
538
- t .Fatalf ("xdsClient.ReportLoad called with {%q}: want {%q}" , got .Server , testLRSServerConfig )
539
- }
540
-
541
- sc1 := <- cc .NewSubConnCh
542
- sc1 .UpdateState (balancer.SubConnState {ConnectivityState : connectivity .Connecting })
543
- // This should get the connecting picker.
544
- if err := cc .WaitForPickerWithErr (ctx , balancer .ErrNoSubConnAvailable ); err != nil {
545
- t .Fatal (err .Error ())
546
- }
547
-
548
- sc1 .UpdateState (balancer.SubConnState {ConnectivityState : connectivity .Ready })
549
- // Test pick with one backend.
550
- testClusterLoadReporter := & testLoadReporter {cluster : testClusterName , service : testServiceName , drops : make (map [string ]uint64 ), localityRPCCount : make (map [clients.Locality ]* rpcCountData )}
551
- const rpcCount = 100
552
- if err := cc .WaitForPicker (ctx , func (p balancer.Picker ) error {
553
- dones := []func (){}
554
- // Override the loadStore in the picker with testClusterLoadReporter.
555
- picker := p .(* picker )
556
- originalLoadStore := picker .loadStore
557
- picker .loadStore = testClusterLoadReporter
558
- defer func () { picker .loadStore = originalLoadStore }()
559
-
560
- for i := 0 ; i < rpcCount ; i ++ {
561
- gotSCSt , err := p .Pick (balancer.PickInfo {})
562
- if i < 50 && err != nil {
563
- return fmt .Errorf ("The first 50%% picks should be non-drops, got error %v" , err )
564
- } else if i > 50 && err == nil {
565
- return fmt .Errorf ("The second 50%% picks should be drops, got error <nil>" )
566
- }
567
- dones = append (dones , func () {
568
- if gotSCSt .Done != nil {
569
- gotSCSt .Done (balancer.DoneInfo {})
570
- }
571
- })
572
- }
573
- for _ , done := range dones {
574
- done ()
575
- }
576
-
577
- dones = []func (){}
578
- // Pick without drops.
579
- for i := 0 ; i < 50 ; i ++ {
580
- gotSCSt , err := p .Pick (balancer.PickInfo {})
581
- if err != nil {
582
- t .Errorf ("The third 50%% picks should be non-drops, got error %v" , err )
583
- }
584
- dones = append (dones , func () {
585
- if gotSCSt .Done != nil {
586
- // Fail these requests to test error counts in the load
587
- // report.
588
- gotSCSt .Done (balancer.DoneInfo {Err : fmt .Errorf ("test error" )})
589
- }
590
- })
591
- }
592
- for _ , done := range dones {
593
- done ()
594
- }
595
-
596
- return nil
597
- }); err != nil {
598
- t .Fatal (err .Error ())
599
- }
600
-
601
- // Dump load data from the store and compare with expected counts.
602
- wantStatsData0 := & loadData {
603
- cluster : testClusterName ,
604
- service : testServiceName ,
605
- totalDrops : uint64 (maxRequest ),
606
- localityStats : map [clients.Locality ]localityData {
607
- {}: {requestStats : requestData {
608
- succeeded : uint64 (rpcCount - maxRequest ),
609
- errored : 50 ,
610
- issued : uint64 (rpcCount - maxRequest + 50 ),
611
- }},
612
- },
613
- }
614
-
615
- gotStatsData0 := testClusterLoadReporter .stats ()
616
- if err := verifyLoadStoreData (wantStatsData0 , gotStatsData0 ); err != nil {
617
- t .Fatal (err )
618
- }
619
- }
620
-
621
280
// TestPickerUpdateAfterClose covers the case where a child policy sends a
622
281
// picker update after the cluster_impl policy is closed. Because picker updates
623
282
// are handled in the run() goroutine, which exits before Close() returns, we
0 commit comments