github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/invoker/invoker_test.go (about)

     1  package invoker
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  
     7  	"github.com/google/uuid"
     8  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
     9  	"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
    10  	"github.com/nspcc-dev/neo-go/pkg/smartcontract"
    11  	"github.com/nspcc-dev/neo-go/pkg/util"
    12  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  type rpcInv struct {
    17  	resInv *result.Invoke
    18  	resTrm bool
    19  	resItm []stackitem.Item
    20  	err    error
    21  }
    22  
    23  func (r *rpcInv) InvokeContractVerify(contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) {
    24  	return r.resInv, r.err
    25  }
    26  func (r *rpcInv) InvokeFunction(contract util.Uint160, operation string, params []smartcontract.Parameter, signers []transaction.Signer) (*result.Invoke, error) {
    27  	return r.resInv, r.err
    28  }
    29  func (r *rpcInv) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) {
    30  	return r.resInv, r.err
    31  }
    32  func (r *rpcInv) InvokeContractVerifyAtHeight(height uint32, contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) {
    33  	return r.resInv, r.err
    34  }
    35  func (r *rpcInv) InvokeContractVerifyWithState(stateroot util.Uint256, contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) {
    36  	return r.resInv, r.err
    37  }
    38  func (r *rpcInv) InvokeFunctionAtHeight(height uint32, contract util.Uint160, operation string, params []smartcontract.Parameter, signers []transaction.Signer) (*result.Invoke, error) {
    39  	return r.resInv, r.err
    40  }
    41  func (r *rpcInv) InvokeFunctionWithState(stateroot util.Uint256, contract util.Uint160, operation string, params []smartcontract.Parameter, signers []transaction.Signer) (*result.Invoke, error) {
    42  	return r.resInv, r.err
    43  }
    44  func (r *rpcInv) InvokeScriptAtHeight(height uint32, script []byte, signers []transaction.Signer) (*result.Invoke, error) {
    45  	return r.resInv, r.err
    46  }
    47  func (r *rpcInv) InvokeScriptWithState(stateroot util.Uint256, script []byte, signers []transaction.Signer) (*result.Invoke, error) {
    48  	return r.resInv, r.err
    49  }
    50  func (r *rpcInv) TerminateSession(sessionID uuid.UUID) (bool, error) {
    51  	return r.resTrm, r.err
    52  }
    53  func (r *rpcInv) TraverseIterator(sessionID, iteratorID uuid.UUID, maxItemsCount int) ([]stackitem.Item, error) {
    54  	return r.resItm, r.err
    55  }
    56  
    57  func TestInvoker(t *testing.T) {
    58  	resExp := &result.Invoke{State: "HALT"}
    59  	ri := &rpcInv{resExp, true, nil, nil}
    60  
    61  	testInv := func(t *testing.T, inv *Invoker) {
    62  		res, err := inv.Call(util.Uint160{}, "method")
    63  		require.NoError(t, err)
    64  		require.Equal(t, resExp, res)
    65  
    66  		res, err = inv.Verify(util.Uint160{}, nil)
    67  		require.NoError(t, err)
    68  		require.Equal(t, resExp, res)
    69  
    70  		res, err = inv.Run([]byte{1})
    71  		require.NoError(t, err)
    72  		require.Equal(t, resExp, res)
    73  
    74  		res, err = inv.Call(util.Uint160{}, "method")
    75  		require.NoError(t, err)
    76  		require.Equal(t, resExp, res)
    77  
    78  		res, err = inv.Verify(util.Uint160{}, nil, "param")
    79  		require.NoError(t, err)
    80  		require.Equal(t, resExp, res)
    81  
    82  		res, err = inv.Call(util.Uint160{}, "method", 42)
    83  		require.NoError(t, err)
    84  		require.Equal(t, resExp, res)
    85  
    86  		_, err = inv.Verify(util.Uint160{}, nil, make(map[int]int))
    87  		require.Error(t, err)
    88  
    89  		_, err = inv.Call(util.Uint160{}, "method", make(map[int]int))
    90  		require.Error(t, err)
    91  
    92  		res, err = inv.CallAndExpandIterator(util.Uint160{}, "method", 10, 42)
    93  		require.NoError(t, err)
    94  		require.Equal(t, resExp, res)
    95  
    96  		_, err = inv.CallAndExpandIterator(util.Uint160{}, "method", 10, make(map[int]int))
    97  		require.Error(t, err)
    98  	}
    99  	t.Run("standard", func(t *testing.T) {
   100  		testInv(t, New(ri, nil))
   101  	})
   102  	t.Run("historic, height", func(t *testing.T) {
   103  		testInv(t, NewHistoricAtHeight(100500, ri, nil))
   104  	})
   105  	t.Run("historic, state", func(t *testing.T) {
   106  		testInv(t, NewHistoricWithState(util.Uint256{}, ri, nil))
   107  	})
   108  	t.Run("broken historic", func(t *testing.T) {
   109  		inv := New(&historicConverter{client: ri}, nil) // It's not possible to do this from outside.
   110  		require.Panics(t, func() { _, _ = inv.Call(util.Uint160{}, "method") })
   111  		require.Panics(t, func() { _, _ = inv.Verify(util.Uint160{}, nil, "param") })
   112  		require.Panics(t, func() { _, _ = inv.Run([]byte{1}) })
   113  	})
   114  	t.Run("terminate session", func(t *testing.T) {
   115  		for _, inv := range []*Invoker{New(ri, nil), NewHistoricWithState(util.Uint256{}, ri, nil)} {
   116  			ri.err = errors.New("")
   117  			require.Error(t, inv.TerminateSession(uuid.UUID{}))
   118  			ri.err = nil
   119  			ri.resTrm = false
   120  			require.Error(t, inv.TerminateSession(uuid.UUID{}))
   121  			ri.resTrm = true
   122  			require.NoError(t, inv.TerminateSession(uuid.UUID{}))
   123  		}
   124  	})
   125  	t.Run("traverse iterator", func(t *testing.T) {
   126  		for _, inv := range []*Invoker{New(ri, nil), NewHistoricWithState(util.Uint256{}, ri, nil)} {
   127  			res, err := inv.TraverseIterator(uuid.UUID{}, &result.Iterator{
   128  				Values: []stackitem.Item{stackitem.Make(42)},
   129  			}, 0)
   130  			require.NoError(t, err)
   131  			require.Equal(t, []stackitem.Item{stackitem.Make(42)}, res)
   132  
   133  			res, err = inv.TraverseIterator(uuid.UUID{}, &result.Iterator{
   134  				Values: []stackitem.Item{stackitem.Make(42)},
   135  			}, 1)
   136  			require.NoError(t, err)
   137  			require.Equal(t, []stackitem.Item{stackitem.Make(42)}, res)
   138  
   139  			res, err = inv.TraverseIterator(uuid.UUID{}, &result.Iterator{
   140  				Values: []stackitem.Item{stackitem.Make(42)},
   141  			}, 2)
   142  			require.NoError(t, err)
   143  			require.Equal(t, []stackitem.Item{stackitem.Make(42)}, res)
   144  
   145  			ri.err = errors.New("")
   146  			_, err = inv.TraverseIterator(uuid.UUID{}, &result.Iterator{
   147  				ID: &uuid.UUID{},
   148  			}, 2)
   149  			require.Error(t, err)
   150  
   151  			ri.err = nil
   152  			ri.resItm = []stackitem.Item{stackitem.Make(42)}
   153  			res, err = inv.TraverseIterator(uuid.UUID{}, &result.Iterator{
   154  				ID: &uuid.UUID{},
   155  			}, 2)
   156  			require.NoError(t, err)
   157  			require.Equal(t, []stackitem.Item{stackitem.Make(42)}, res)
   158  		}
   159  	})
   160  }