github.com/vipernet-xyz/tm@v0.34.24/test/e2e/runner/rpc.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"time"
     8  
     9  	rpchttp "github.com/vipernet-xyz/tm/rpc/client/http"
    10  	rpctypes "github.com/vipernet-xyz/tm/rpc/core/types"
    11  	e2e "github.com/vipernet-xyz/tm/test/e2e/pkg"
    12  	"github.com/vipernet-xyz/tm/types"
    13  )
    14  
    15  // waitForHeight waits for the network to reach a certain height (or above),
    16  // returning the highest height seen. Errors if the network is not making
    17  // progress at all.
    18  func waitForHeight(testnet *e2e.Testnet, height int64) (*types.Block, *types.BlockID, error) {
    19  	var (
    20  		err          error
    21  		maxResult    *rpctypes.ResultBlock
    22  		clients      = map[string]*rpchttp.HTTP{}
    23  		lastIncrease = time.Now()
    24  	)
    25  
    26  	for {
    27  		for _, node := range testnet.Nodes {
    28  			if node.Mode == e2e.ModeSeed {
    29  				continue
    30  			}
    31  			client, ok := clients[node.Name]
    32  			if !ok {
    33  				client, err = node.Client()
    34  				if err != nil {
    35  					continue
    36  				}
    37  				clients[node.Name] = client
    38  			}
    39  
    40  			ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
    41  			defer cancel()
    42  			result, err := client.Block(ctx, nil)
    43  			if err != nil {
    44  				continue
    45  			}
    46  			if result.Block != nil && (maxResult == nil || result.Block.Height >= maxResult.Block.Height) {
    47  				maxResult = result
    48  				lastIncrease = time.Now()
    49  			}
    50  			if maxResult != nil && maxResult.Block.Height >= height {
    51  				return maxResult.Block, &maxResult.BlockID, nil
    52  			}
    53  		}
    54  
    55  		if len(clients) == 0 {
    56  			return nil, nil, errors.New("unable to connect to any network nodes")
    57  		}
    58  		if time.Since(lastIncrease) >= 20*time.Second {
    59  			if maxResult == nil {
    60  				return nil, nil, errors.New("chain stalled at unknown height")
    61  			}
    62  			return nil, nil, fmt.Errorf("chain stalled at height %v", maxResult.Block.Height)
    63  		}
    64  		time.Sleep(1 * time.Second)
    65  	}
    66  }
    67  
    68  // waitForNode waits for a node to become available and catch up to the given block height.
    69  func waitForNode(node *e2e.Node, height int64, timeout time.Duration) (*rpctypes.ResultStatus, error) {
    70  	client, err := node.Client()
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	ctx, cancel := context.WithTimeout(context.Background(), timeout)
    75  	defer cancel()
    76  	for {
    77  		status, err := client.Status(ctx)
    78  		switch {
    79  		case errors.Is(err, context.DeadlineExceeded):
    80  			return nil, fmt.Errorf("timed out waiting for %v to reach height %v", node.Name, height)
    81  		case errors.Is(err, context.Canceled):
    82  			return nil, err
    83  		case err == nil && status.SyncInfo.LatestBlockHeight >= height:
    84  			return status, nil
    85  		}
    86  
    87  		time.Sleep(300 * time.Millisecond)
    88  	}
    89  }
    90  
    91  // waitForAllNodes waits for all nodes to become available and catch up to the given block height.
    92  func waitForAllNodes(testnet *e2e.Testnet, height int64, timeout time.Duration) (int64, error) {
    93  	var lastHeight int64
    94  
    95  	for _, node := range testnet.Nodes {
    96  		if node.Mode == e2e.ModeSeed {
    97  			continue
    98  		}
    99  
   100  		status, err := waitForNode(node, height, timeout)
   101  		if err != nil {
   102  			return 0, err
   103  		}
   104  
   105  		if status.SyncInfo.LatestBlockHeight > lastHeight {
   106  			lastHeight = status.SyncInfo.LatestBlockHeight
   107  		}
   108  	}
   109  
   110  	return lastHeight, nil
   111  }