google.golang.org/grpc@v1.62.1/xds/internal/balancer/outlierdetection/callcounter_test.go (about) 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 }