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 }