...

Source file src/google.golang.org/grpc/xds/internal/balancer/outlierdetection/callcounter_test.go

Documentation: google.golang.org/grpc/xds/internal/balancer/outlierdetection

     1  /*
     2   *
     3   * Copyright 2022 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package outlierdetection
    19  
    20  import (
    21  	"sync/atomic"
    22  	"testing"
    23  	"unsafe"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  )
    27  
    28  func (b1 *bucket) Equal(b2 *bucket) bool {
    29  	if b1 == nil && b2 == nil {
    30  		return true
    31  	}
    32  	if (b1 != nil) != (b2 != nil) {
    33  		return false
    34  	}
    35  	if b1.numSuccesses != b2.numSuccesses {
    36  		return false
    37  	}
    38  	return b1.numFailures == b2.numFailures
    39  }
    40  
    41  func (cc *callCounter) Equal(cc2 *callCounter) bool {
    42  	if cc == nil && cc2 == nil {
    43  		return true
    44  	}
    45  	if (cc != nil) != (cc2 != nil) {
    46  		return false
    47  	}
    48  	ab1 := (*bucket)(atomic.LoadPointer(&cc.activeBucket))
    49  	ab2 := (*bucket)(atomic.LoadPointer(&cc2.activeBucket))
    50  	if !ab1.Equal(ab2) {
    51  		return false
    52  	}
    53  	return cc.inactiveBucket.Equal(cc2.inactiveBucket)
    54  }
    55  
    56  // TestClear tests that clear on the call counter clears (everything set to 0)
    57  // the active and inactive buckets.
    58  func (s) TestClear(t *testing.T) {
    59  	cc := newCallCounter()
    60  	ab := (*bucket)(atomic.LoadPointer(&cc.activeBucket))
    61  	ab.numSuccesses = 1
    62  	ab.numFailures = 2
    63  	cc.inactiveBucket.numSuccesses = 4
    64  	cc.inactiveBucket.numFailures = 5
    65  	cc.clear()
    66  	// Both the active and inactive buckets should be cleared.
    67  	ccWant := newCallCounter()
    68  	if diff := cmp.Diff(cc, ccWant); diff != "" {
    69  		t.Fatalf("callCounter is different than expected, diff (-got +want): %v", diff)
    70  	}
    71  }
    72  
    73  // TestSwap tests that swap() on the callCounter successfully has the desired
    74  // end result of inactive bucket containing the previous active buckets data,
    75  // and the active bucket being cleared.
    76  func (s) TestSwap(t *testing.T) {
    77  	cc := newCallCounter()
    78  	ab := (*bucket)(atomic.LoadPointer(&cc.activeBucket))
    79  	ab.numSuccesses = 1
    80  	ab.numFailures = 2
    81  	cc.inactiveBucket.numSuccesses = 4
    82  	cc.inactiveBucket.numFailures = 5
    83  	ib := cc.inactiveBucket
    84  	cc.swap()
    85  	// Inactive should pick up active's data, active should be swapped to zeroed
    86  	// inactive.
    87  	ccWant := newCallCounter()
    88  	ccWant.inactiveBucket.numSuccesses = 1
    89  	ccWant.inactiveBucket.numFailures = 2
    90  	atomic.StorePointer(&ccWant.activeBucket, unsafe.Pointer(ib))
    91  	if diff := cmp.Diff(cc, ccWant); diff != "" {
    92  		t.Fatalf("callCounter is different than expected, diff (-got +want): %v", diff)
    93  	}
    94  }
    95  

View as plain text