...

Source file src/google.golang.org/grpc/internal/testutils/state.go

Documentation: google.golang.org/grpc/internal/testutils

     1  /*
     2   *
     3   * Copyright 2023 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  
    19  package testutils
    20  
    21  import (
    22  	"context"
    23  	"testing"
    24  
    25  	"google.golang.org/grpc/connectivity"
    26  )
    27  
    28  // A StateChanger reports state changes, e.g. a grpc.ClientConn.
    29  type StateChanger interface {
    30  	// Connect begins connecting the StateChanger.
    31  	Connect()
    32  	// GetState returns the current state of the StateChanger.
    33  	GetState() connectivity.State
    34  	// WaitForStateChange returns true when the state becomes s, or returns
    35  	// false if ctx is canceled first.
    36  	WaitForStateChange(ctx context.Context, s connectivity.State) bool
    37  }
    38  
    39  // StayConnected makes sc stay connected by repeatedly calling sc.Connect()
    40  // until the state becomes Shutdown or until ithe context expires.
    41  func StayConnected(ctx context.Context, sc StateChanger) {
    42  	for {
    43  		state := sc.GetState()
    44  		switch state {
    45  		case connectivity.Idle:
    46  			sc.Connect()
    47  		case connectivity.Shutdown:
    48  			return
    49  		}
    50  		if !sc.WaitForStateChange(ctx, state) {
    51  			return
    52  		}
    53  	}
    54  }
    55  
    56  // AwaitState waits for sc to enter stateWant or fatal errors if it doesn't
    57  // happen before ctx expires.
    58  func AwaitState(ctx context.Context, t *testing.T, sc StateChanger, stateWant connectivity.State) {
    59  	t.Helper()
    60  	for state := sc.GetState(); state != stateWant; state = sc.GetState() {
    61  		if !sc.WaitForStateChange(ctx, state) {
    62  			t.Fatalf("Timed out waiting for state change.  got %v; want %v", state, stateWant)
    63  		}
    64  	}
    65  }
    66  
    67  // AwaitNotState waits for sc to leave stateDoNotWant or fatal errors if it
    68  // doesn't happen before ctx expires.
    69  func AwaitNotState(ctx context.Context, t *testing.T, sc StateChanger, stateDoNotWant connectivity.State) {
    70  	t.Helper()
    71  	for state := sc.GetState(); state == stateDoNotWant; state = sc.GetState() {
    72  		if !sc.WaitForStateChange(ctx, state) {
    73  			t.Fatalf("Timed out waiting for state change.  got %v; want NOT %v", state, stateDoNotWant)
    74  		}
    75  	}
    76  }
    77  
    78  // AwaitNoStateChange expects ctx to be canceled before sc's state leaves
    79  // currState, and fatal errors otherwise.
    80  func AwaitNoStateChange(ctx context.Context, t *testing.T, sc StateChanger, currState connectivity.State) {
    81  	t.Helper()
    82  	if sc.WaitForStateChange(ctx, currState) {
    83  		t.Fatalf("State changed from %q to %q when no state change was expected", currState, sc.GetState())
    84  	}
    85  }
    86  

View as plain text