github.com/MetalBlockchain/metalgo@v1.11.9/tests/fixture/tmpnet/utils.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package tmpnet
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"errors"
    10  	"fmt"
    11  	"time"
    12  
    13  	"github.com/MetalBlockchain/metalgo/ids"
    14  	"github.com/MetalBlockchain/metalgo/utils/crypto/secp256k1"
    15  )
    16  
    17  const (
    18  	DefaultNodeTickerInterval = 50 * time.Millisecond
    19  )
    20  
    21  var ErrNotRunning = errors.New("not running")
    22  
    23  // WaitForHealthy blocks until Node.IsHealthy returns true or an error (including context timeout) is observed.
    24  func WaitForHealthy(ctx context.Context, node *Node) error {
    25  	if _, ok := ctx.Deadline(); !ok {
    26  		return fmt.Errorf("unable to wait for health for node %q with a context without a deadline", node.NodeID)
    27  	}
    28  	ticker := time.NewTicker(DefaultNodeTickerInterval)
    29  	defer ticker.Stop()
    30  
    31  	for {
    32  		healthy, err := node.IsHealthy(ctx)
    33  		if err != nil && !errors.Is(err, ErrNotRunning) {
    34  			return fmt.Errorf("failed to wait for health of node %q: %w", node.NodeID, err)
    35  		}
    36  		if healthy {
    37  			return nil
    38  		}
    39  
    40  		select {
    41  		case <-ctx.Done():
    42  			return fmt.Errorf("failed to wait for health of node %q before timeout: %w", node.NodeID, ctx.Err())
    43  		case <-ticker.C:
    44  		}
    45  	}
    46  }
    47  
    48  // NodeURI associates a node ID with its API URI.
    49  type NodeURI struct {
    50  	NodeID ids.NodeID
    51  	URI    string
    52  }
    53  
    54  func GetNodeURIs(nodes []*Node) []NodeURI {
    55  	uris := make([]NodeURI, 0, len(nodes))
    56  	for _, node := range nodes {
    57  		if node.IsEphemeral {
    58  			// Avoid returning URIs for nodes whose lifespan is indeterminate
    59  			continue
    60  		}
    61  		// Only append URIs that are not empty. A node may have an
    62  		// empty URI if it is not currently running.
    63  		if len(node.URI) > 0 {
    64  			uris = append(uris, NodeURI{
    65  				NodeID: node.NodeID,
    66  				URI:    node.URI,
    67  			})
    68  		}
    69  	}
    70  	return uris
    71  }
    72  
    73  // Marshal to json with default prefix and indent.
    74  func DefaultJSONMarshal(v interface{}) ([]byte, error) {
    75  	return json.MarshalIndent(v, "", "  ")
    76  }
    77  
    78  // Helper simplifying creation of a set of private keys
    79  func NewPrivateKeys(keyCount int) ([]*secp256k1.PrivateKey, error) {
    80  	keys := make([]*secp256k1.PrivateKey, 0, keyCount)
    81  	for i := 0; i < keyCount; i++ {
    82  		key, err := secp256k1.NewPrivateKey()
    83  		if err != nil {
    84  			return nil, fmt.Errorf("failed to generate private key: %w", err)
    85  		}
    86  		keys = append(keys, key)
    87  	}
    88  	return keys, nil
    89  }
    90  
    91  func NodesToIDs(nodes ...*Node) []ids.NodeID {
    92  	nodeIDs := make([]ids.NodeID, len(nodes))
    93  	for i, node := range nodes {
    94  		nodeIDs[i] = node.NodeID
    95  	}
    96  	return nodeIDs
    97  }