github.com/vipernet-xyz/tendermint-core@v0.32.0/rpc/client/mock/abci.go (about)

     1  package mock
     2  
     3  import (
     4  	abci "github.com/tendermint/tendermint/abci/types"
     5  	"github.com/tendermint/tendermint/libs/bytes"
     6  	"github.com/tendermint/tendermint/proxy"
     7  	"github.com/tendermint/tendermint/rpc/client"
     8  	ctypes "github.com/tendermint/tendermint/rpc/core/types"
     9  	"github.com/tendermint/tendermint/types"
    10  )
    11  
    12  // ABCIApp will send all abci related request to the named app,
    13  // so you can test app behavior from a client without needing
    14  // an entire tendermint node
    15  type ABCIApp struct {
    16  	App abci.Application
    17  }
    18  
    19  var (
    20  	_ client.ABCIClient = ABCIApp{}
    21  	_ client.ABCIClient = ABCIMock{}
    22  	_ client.ABCIClient = (*ABCIRecorder)(nil)
    23  )
    24  
    25  func (a ABCIApp) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
    26  	return &ctypes.ResultABCIInfo{Response: a.App.Info(proxy.RequestInfo)}, nil
    27  }
    28  
    29  func (a ABCIApp) ABCIQuery(path string, data bytes.HexBytes) (*ctypes.ResultABCIQuery, error) {
    30  	return a.ABCIQueryWithOptions(path, data, client.DefaultABCIQueryOptions)
    31  }
    32  
    33  func (a ABCIApp) ABCIQueryWithOptions(
    34  	path string,
    35  	data bytes.HexBytes,
    36  	opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
    37  	q := a.App.Query(abci.RequestQuery{
    38  		Data:   data,
    39  		Path:   path,
    40  		Height: opts.Height,
    41  		Prove:  opts.Prove,
    42  	})
    43  	return &ctypes.ResultABCIQuery{Response: q}, nil
    44  }
    45  
    46  // NOTE: Caller should call a.App.Commit() separately,
    47  // this function does not actually wait for a commit.
    48  // TODO: Make it wait for a commit and set res.Height appropriately.
    49  func (a ABCIApp) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
    50  	res := ctypes.ResultBroadcastTxCommit{}
    51  	res.CheckTx = a.App.CheckTx(abci.RequestCheckTx{Tx: tx})
    52  	if res.CheckTx.IsErr() {
    53  		return &res, nil
    54  	}
    55  	res.DeliverTx = a.App.DeliverTx(abci.RequestDeliverTx{Tx: tx})
    56  	res.Height = -1 // TODO
    57  	return &res, nil
    58  }
    59  
    60  func (a ABCIApp) BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
    61  	c := a.App.CheckTx(abci.RequestCheckTx{Tx: tx})
    62  	// and this gets written in a background thread...
    63  	if !c.IsErr() {
    64  		go func() { a.App.DeliverTx(abci.RequestDeliverTx{Tx: tx}) }() // nolint: errcheck
    65  	}
    66  	return &ctypes.ResultBroadcastTx{
    67  		Code:      c.Code,
    68  		Data:      c.Data,
    69  		Log:       c.Log,
    70  		Codespace: c.Codespace,
    71  		Hash:      tx.Hash(),
    72  	}, nil
    73  }
    74  
    75  func (a ABCIApp) BroadcastTxSync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
    76  	c := a.App.CheckTx(abci.RequestCheckTx{Tx: tx})
    77  	// and this gets written in a background thread...
    78  	if !c.IsErr() {
    79  		go func() { a.App.DeliverTx(abci.RequestDeliverTx{Tx: tx}) }() // nolint: errcheck
    80  	}
    81  	return &ctypes.ResultBroadcastTx{
    82  		Code:      c.Code,
    83  		Data:      c.Data,
    84  		Log:       c.Log,
    85  		Codespace: c.Codespace,
    86  		Hash:      tx.Hash(),
    87  	}, nil
    88  }
    89  
    90  // ABCIMock will send all abci related request to the named app,
    91  // so you can test app behavior from a client without needing
    92  // an entire tendermint node
    93  type ABCIMock struct {
    94  	Info            Call
    95  	Query           Call
    96  	BroadcastCommit Call
    97  	Broadcast       Call
    98  }
    99  
   100  func (m ABCIMock) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
   101  	res, err := m.Info.GetResponse(nil)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	return &ctypes.ResultABCIInfo{Response: res.(abci.ResponseInfo)}, nil
   106  }
   107  
   108  func (m ABCIMock) ABCIQuery(path string, data bytes.HexBytes) (*ctypes.ResultABCIQuery, error) {
   109  	return m.ABCIQueryWithOptions(path, data, client.DefaultABCIQueryOptions)
   110  }
   111  
   112  func (m ABCIMock) ABCIQueryWithOptions(
   113  	path string,
   114  	data bytes.HexBytes,
   115  	opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
   116  	res, err := m.Query.GetResponse(QueryArgs{path, data, opts.Height, opts.Prove})
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  	resQuery := res.(abci.ResponseQuery)
   121  	return &ctypes.ResultABCIQuery{Response: resQuery}, nil
   122  }
   123  
   124  func (m ABCIMock) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
   125  	res, err := m.BroadcastCommit.GetResponse(tx)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  	return res.(*ctypes.ResultBroadcastTxCommit), nil
   130  }
   131  
   132  func (m ABCIMock) BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   133  	res, err := m.Broadcast.GetResponse(tx)
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  	return res.(*ctypes.ResultBroadcastTx), nil
   138  }
   139  
   140  func (m ABCIMock) BroadcastTxSync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   141  	res, err := m.Broadcast.GetResponse(tx)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  	return res.(*ctypes.ResultBroadcastTx), nil
   146  }
   147  
   148  // ABCIRecorder can wrap another type (ABCIApp, ABCIMock, or Client)
   149  // and record all ABCI related calls.
   150  type ABCIRecorder struct {
   151  	Client client.ABCIClient
   152  	Calls  []Call
   153  }
   154  
   155  func NewABCIRecorder(client client.ABCIClient) *ABCIRecorder {
   156  	return &ABCIRecorder{
   157  		Client: client,
   158  		Calls:  []Call{},
   159  	}
   160  }
   161  
   162  type QueryArgs struct {
   163  	Path   string
   164  	Data   bytes.HexBytes
   165  	Height int64
   166  	Prove  bool
   167  }
   168  
   169  func (r *ABCIRecorder) addCall(call Call) {
   170  	r.Calls = append(r.Calls, call)
   171  }
   172  
   173  func (r *ABCIRecorder) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
   174  	res, err := r.Client.ABCIInfo()
   175  	r.addCall(Call{
   176  		Name:     "abci_info",
   177  		Response: res,
   178  		Error:    err,
   179  	})
   180  	return res, err
   181  }
   182  
   183  func (r *ABCIRecorder) ABCIQuery(path string, data bytes.HexBytes) (*ctypes.ResultABCIQuery, error) {
   184  	return r.ABCIQueryWithOptions(path, data, client.DefaultABCIQueryOptions)
   185  }
   186  
   187  func (r *ABCIRecorder) ABCIQueryWithOptions(
   188  	path string,
   189  	data bytes.HexBytes,
   190  	opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
   191  	res, err := r.Client.ABCIQueryWithOptions(path, data, opts)
   192  	r.addCall(Call{
   193  		Name:     "abci_query",
   194  		Args:     QueryArgs{path, data, opts.Height, opts.Prove},
   195  		Response: res,
   196  		Error:    err,
   197  	})
   198  	return res, err
   199  }
   200  
   201  func (r *ABCIRecorder) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
   202  	res, err := r.Client.BroadcastTxCommit(tx)
   203  	r.addCall(Call{
   204  		Name:     "broadcast_tx_commit",
   205  		Args:     tx,
   206  		Response: res,
   207  		Error:    err,
   208  	})
   209  	return res, err
   210  }
   211  
   212  func (r *ABCIRecorder) BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   213  	res, err := r.Client.BroadcastTxAsync(tx)
   214  	r.addCall(Call{
   215  		Name:     "broadcast_tx_async",
   216  		Args:     tx,
   217  		Response: res,
   218  		Error:    err,
   219  	})
   220  	return res, err
   221  }
   222  
   223  func (r *ABCIRecorder) BroadcastTxSync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   224  	res, err := r.Client.BroadcastTxSync(tx)
   225  	r.addCall(Call{
   226  		Name:     "broadcast_tx_sync",
   227  		Args:     tx,
   228  		Response: res,
   229  		Error:    err,
   230  	})
   231  	return res, err
   232  }