github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/tests/util.go (about)

     1  package tests
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	rpchttp "github.com/fibonacci-chain/fbc/libs/tendermint/rpc/client/http"
    13  	ctypes "github.com/fibonacci-chain/fbc/libs/tendermint/rpc/core/types"
    14  	tmjsonrpc "github.com/fibonacci-chain/fbc/libs/tendermint/rpc/jsonrpc/client"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    18  )
    19  
    20  // Wait for the next tendermint block from the Tendermint RPC
    21  // on localhost
    22  func WaitForNextHeightTM(port string) {
    23  	WaitForNextNBlocksTM(1, port)
    24  }
    25  
    26  // Wait for N tendermint blocks to pass using the Tendermint RPC
    27  // on localhost
    28  func WaitForNextNBlocksTM(n int64, port string) {
    29  	// get the latest block and wait for n more
    30  	url := fmt.Sprintf("http://localhost:%v", port)
    31  	cl, err := rpchttp.New(url, "/websocket")
    32  	if err != nil {
    33  		panic(fmt.Sprintf("failed to create Tendermint HTTP client: %s", err))
    34  	}
    35  
    36  	var height int64
    37  
    38  	resBlock, err := cl.Block(nil)
    39  	if err != nil || resBlock.Block == nil {
    40  		// wait for the first block to exist
    41  		WaitForHeightTM(1, port)
    42  		height = 1 + n
    43  	} else {
    44  		height = resBlock.Block.Height + n
    45  	}
    46  
    47  	waitForHeightTM(height, url)
    48  }
    49  
    50  // Wait for the given height from the Tendermint RPC
    51  // on localhost
    52  func WaitForHeightTM(height int64, port string) {
    53  	url := fmt.Sprintf("http://localhost:%v", port)
    54  	waitForHeightTM(height, url)
    55  }
    56  
    57  func waitForHeightTM(height int64, url string) {
    58  	cl, err := rpchttp.New(url, "/websocket")
    59  	if err != nil {
    60  		panic(fmt.Sprintf("failed to create Tendermint HTTP client: %s", err))
    61  	}
    62  
    63  	for {
    64  		// get url, try a few times
    65  		var resBlock *ctypes.ResultBlock
    66  		var err error
    67  	INNER:
    68  		for i := 0; i < 5; i++ {
    69  			resBlock, err = cl.Block(nil)
    70  			if err == nil {
    71  				break INNER
    72  			}
    73  			time.Sleep(time.Millisecond * 200)
    74  		}
    75  		if err != nil {
    76  			panic(err)
    77  		}
    78  
    79  		if resBlock.Block != nil && resBlock.Block.Height >= height {
    80  			return
    81  		}
    82  
    83  		time.Sleep(time.Millisecond * 100)
    84  	}
    85  }
    86  
    87  // Wait for height from the LCD API on localhost
    88  func WaitForHeight(height int64, port string) {
    89  	url := fmt.Sprintf("http://localhost:%v/blocks/latest", port)
    90  	waitForHeight(height, url)
    91  }
    92  
    93  // Whether or not an HTTP status code was "successful"
    94  func StatusOK(statusCode int) bool {
    95  	switch statusCode {
    96  	case http.StatusOK:
    97  	case http.StatusCreated:
    98  	case http.StatusNoContent:
    99  		return true
   100  	}
   101  	return false
   102  }
   103  
   104  func waitForHeight(height int64, url string) {
   105  	var res *http.Response
   106  	var err error
   107  
   108  	for {
   109  		// Since this is in a testing file we are accepting nolint to be passed
   110  		res, err = http.Get(url) // nolint:gosec
   111  		if err != nil {
   112  			panic(err)
   113  		}
   114  
   115  		body, err := ioutil.ReadAll(res.Body)
   116  		if err != nil {
   117  			panic(err)
   118  		}
   119  
   120  		if err = res.Body.Close(); err != nil {
   121  			panic(err)
   122  		}
   123  
   124  		var resultBlock ctypes.ResultBlock
   125  		if err = cdc.UnmarshalJSON(body, &resultBlock); err != nil {
   126  			panic(err)
   127  		}
   128  
   129  		if resultBlock.Block != nil && resultBlock.Block.Height >= height {
   130  			return
   131  		}
   132  
   133  		time.Sleep(time.Millisecond * 100)
   134  	}
   135  }
   136  
   137  // wait for tendermint to start by querying the LCD
   138  func WaitForLCDStart(port string) {
   139  	url := fmt.Sprintf("http://localhost:%v/blocks/latest", port)
   140  	WaitForStart(url)
   141  }
   142  
   143  // wait for tendermint to start by querying tendermint
   144  func WaitForTMStart(port string) {
   145  	url := fmt.Sprintf("http://localhost:%v/block", port)
   146  	WaitForStart(url)
   147  }
   148  
   149  // WaitForStart waits for the node to start by pinging the url
   150  // every 100ms for 10s until it returns 200. If it takes longer than 5s,
   151  // it panics.
   152  func WaitForStart(url string) {
   153  	var err error
   154  
   155  	// ping the status endpoint a few times a second
   156  	// for a few seconds until we get a good response.
   157  	// otherwise something probably went wrong
   158  	for i := 0; i < 100; i++ {
   159  		time.Sleep(time.Millisecond * 100)
   160  
   161  		var res *http.Response
   162  		res, err = http.Get(url) // nolint:gosec
   163  		if err != nil || res == nil {
   164  			continue
   165  		}
   166  		//		body, _ := ioutil.ReadAll(res.Body)
   167  		//		fmt.Println("BODY", string(body))
   168  		err = res.Body.Close()
   169  		if err != nil {
   170  			panic(err)
   171  		}
   172  
   173  		if res.StatusCode == http.StatusOK {
   174  			// good!
   175  			return
   176  		}
   177  	}
   178  	// still haven't started up?! panic!
   179  	panic(err)
   180  }
   181  
   182  // Wait for the RPC server to respond to /status
   183  func WaitForRPC(laddr string) {
   184  	fmt.Println("LADDR", laddr)
   185  	client, err := tmjsonrpc.New(laddr)
   186  	if err != nil {
   187  		panic(fmt.Sprintf("failed to create Tendermint RPC client: %s", err))
   188  	}
   189  
   190  	ctypes.RegisterAmino(client.Codec())
   191  	result := new(ctypes.ResultStatus)
   192  	for {
   193  		_, err := client.Call("status", map[string]interface{}{}, result)
   194  		if err == nil {
   195  			return
   196  		}
   197  		fmt.Printf("Waiting for RPC server to start on %s:%v\n", laddr, err)
   198  		time.Sleep(time.Millisecond)
   199  	}
   200  }
   201  
   202  // ExtractPortFromAddress extract port from listenAddress
   203  // The listenAddress must be some strings like tcp://0.0.0.0:12345
   204  func ExtractPortFromAddress(listenAddress string) string {
   205  	stringList := strings.Split(listenAddress, ":")
   206  	length := len(stringList)
   207  	if length != 3 {
   208  		panic(fmt.Errorf("expected listen address: tcp://0.0.0.0:12345, got %s", listenAddress))
   209  	}
   210  	return stringList[2]
   211  }
   212  
   213  // NewTestCaseDir creates a new temporary directory for a test case.
   214  // Returns the directory path and a cleanup function.
   215  // nolint: errcheck
   216  func NewTestCaseDir(t *testing.T) (string, func()) {
   217  	dir, err := ioutil.TempDir("", t.Name()+"_")
   218  	require.NoError(t, err)
   219  	return dir, func() { os.RemoveAll(dir) }
   220  }
   221  
   222  var cdc = codec.New()
   223  
   224  func init() {
   225  	ctypes.RegisterAmino(cdc)
   226  }
   227  
   228  //DONTCOVER