github.com/evdatsion/aphelion-dpos-bft@v0.32.1/rpc/client/mock/abci.go (about)

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