github.com/igggame/nebulas-go@v2.1.0+incompatible/nf/nvm/engine_blockchian_test.go (about)

     1  package nvm
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"testing"
     7  
     8  	"github.com/gogo/protobuf/proto"
     9  	"github.com/nebulasio/go-nebulas/consensus/dpos"
    10  	"github.com/nebulasio/go-nebulas/core"
    11  	"github.com/nebulasio/go-nebulas/core/pb"
    12  	"github.com/nebulasio/go-nebulas/core/state"
    13  	"github.com/nebulasio/go-nebulas/storage"
    14  	"github.com/nebulasio/go-nebulas/util/byteutils"
    15  	"github.com/stretchr/testify/assert"
    16  )
    17  
    18  func TestBlockChain(t *testing.T) {
    19  	tests := []struct {
    20  		filepath    string
    21  		expectedErr error
    22  	}{
    23  		{"test/test_blockchain.js", nil},
    24  	}
    25  
    26  	for _, tt := range tests {
    27  		t.Run(tt.filepath, func(t *testing.T) {
    28  			data, err := ioutil.ReadFile(tt.filepath)
    29  			assert.Nil(t, err, "filepath read error")
    30  
    31  			mem, _ := storage.NewMemoryStorage()
    32  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
    33  			addr, _ := core.AddressParse("n1FkntVUMPAsESuCAAPK711omQk19JotBjM")
    34  			owner, err := context.GetOrCreateUserAccount(addr.Bytes())
    35  			assert.Nil(t, err)
    36  			owner.AddBalance(newUint128FromIntWrapper(1000000000))
    37  			addr, _ = core.AddressParse("n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR")
    38  			contract, err := context.CreateContractAccount(addr.Bytes(), nil, nil)
    39  			assert.Nil(t, err)
    40  
    41  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
    42  			engine := NewV8Engine(ctx)
    43  			engine.SetExecutionLimits(100000, 10000000)
    44  			_, err = engine.RunScriptSource(string(data), 0)
    45  			assert.Equal(t, tt.expectedErr, err)
    46  			engine.Dispose()
    47  		})
    48  	}
    49  }
    50  
    51  func TestContractFeatureGetAccountState(t *testing.T) {
    52  	type fields struct {
    53  		function string
    54  		args     string
    55  		result   string
    56  		error    string
    57  	}
    58  	tests := []struct {
    59  		contract   string
    60  		sourceType string
    61  		initArgs   string
    62  		calls      []fields
    63  	}{
    64  		{
    65  			"./test/test_contract_features.js",
    66  			"js",
    67  			"[]",
    68  			[]fields{
    69  				{"testGetAccountState", "[]", "\"1000000000000\"", ""},
    70  				{"testGetAccountStateWrongAddr", "[]", "\"0\"", ""},
    71  			},
    72  		},
    73  	}
    74  
    75  	account1 := "n1FkntVUMPAsESuCAAPK711omQk19JotBjM"
    76  	account2 := "n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR"
    77  
    78  	for _, tt := range tests {
    79  		t.Run(tt.contract, func(t *testing.T) {
    80  			data, err := ioutil.ReadFile(tt.contract)
    81  			assert.Nil(t, err, "contract path read error")
    82  
    83  			mem, _ := storage.NewMemoryStorage()
    84  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
    85  			add1, _ := core.AddressParse(account1)
    86  			owner, err := context.GetOrCreateUserAccount(add1.Bytes())
    87  			assert.Nil(t, err)
    88  			owner.AddBalance(newUint128FromIntWrapper(1000000000000))
    89  			add2, _ := core.AddressParse(account2)
    90  			contract, err := context.CreateContractAccount(add2.Bytes(), nil, &corepb.ContractMeta{Version: "1.0.5"})
    91  			assert.Nil(t, err)
    92  			tx := mockNormalTransaction("n1FkntVUMPAsESuCAAPK711omQk19JotBjM", "n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR", "0")
    93  			ctx, err := NewContext(mockBlockForLib(2000000), tx, contract, context)
    94  
    95  			// deploy and init.
    96  			engine := NewV8Engine(ctx)
    97  			engine.SetExecutionLimits(100000, 10000000)
    98  			_, err = engine.DeployAndInit(string(data), tt.sourceType, tt.initArgs)
    99  			assert.Nil(t, err)
   100  			engine.Dispose()
   101  
   102  			// call.
   103  			for _, fields := range tt.calls {
   104  				state, _ := ctx.state.GetOrCreateUserAccount([]byte(account1))
   105  				fmt.Println("===", state)
   106  				engine = NewV8Engine(ctx)
   107  				engine.SetExecutionLimits(100000, 10000000)
   108  				result, err := engine.Call(string(data), tt.sourceType, fields.function, fields.args)
   109  				assert.Equal(t, fields.result, result)
   110  				assert.Nil(t, err)
   111  				engine.Dispose()
   112  			}
   113  		})
   114  	}
   115  }
   116  
   117  func TestContractsFeatureGetBlockHashAndSeed(t *testing.T) {
   118  	type fields struct {
   119  		function string
   120  		args     string
   121  		result   string
   122  		err      error
   123  	}
   124  	tests := []struct {
   125  		contract   string
   126  		sourceType string
   127  		initArgs   string
   128  		calls      []fields
   129  	}{
   130  		{
   131  			"./test/test_contract_features.js",
   132  			"js",
   133  			"[]",
   134  			[]fields{
   135  				{"testGetPreBlockHash1", "[1]", "\"" + byteutils.Hex([]byte("blockHash")) + "\"", nil},
   136  				{"testGetPreBlockHash1", "[0]", "getPreBlockHash: invalid offset", core.ErrExecutionFailed},
   137  				{"testGetPreBlockHashByNativeBlock", "[1.1]", "Blockchain.GetPreBlockHash(), argument must be integer", core.ErrExecutionFailed},
   138  				{"testGetPreBlockSeedByNativeBlock", "[1.1]", "Blockchain.GetPreBlockSeed(), argument must be integer", core.ErrExecutionFailed},
   139  				{"testGetPreBlockHash1", "[1111111111111111111]", "getPreBlockHash: block not exist", core.ErrExecutionFailed},
   140  				{"testGetPreBlockSeed1", "[1]", "\"" + byteutils.Hex([]byte("randomSeed")) + "\"", nil},
   141  			},
   142  		},
   143  	}
   144  
   145  	account1 := "n1FkntVUMPAsESuCAAPK711omQk19JotBjM"
   146  	account2 := "n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR"
   147  
   148  	for _, tt := range tests {
   149  		t.Run(tt.contract, func(t *testing.T) {
   150  			data, err := ioutil.ReadFile(tt.contract)
   151  			assert.Nil(t, err, "contract path read error")
   152  
   153  			mem, _ := storage.NewMemoryStorage()
   154  			curBlock := mockBlockForLib(2000000)
   155  
   156  			preBlock := &corepb.Block{
   157  				Header: &corepb.BlockHeader{
   158  					Random: &corepb.Random{
   159  						VrfSeed: []byte("randomSeed"),
   160  					},
   161  				},
   162  			}
   163  			preBlockHash := []byte("blockHash")
   164  			preBlockHeight := curBlock.Height() - 1
   165  			blockBytes, err := proto.Marshal(preBlock)
   166  			assert.Nil(t, err)
   167  
   168  			mem.Put(byteutils.FromUint64(preBlockHeight), preBlockHash)
   169  			mem.Put(preBlockHash, blockBytes)
   170  
   171  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   172  			add1, _ := core.AddressParse(account1)
   173  			owner, err := context.GetOrCreateUserAccount(add1.Bytes())
   174  			assert.Nil(t, err)
   175  			owner.AddBalance(newUint128FromIntWrapper(1000000000000))
   176  			add2, _ := core.AddressParse(account2)
   177  			contract, err := context.CreateContractAccount(add2.Bytes(), nil, &corepb.ContractMeta{Version: "1.0.5"})
   178  			assert.Nil(t, err)
   179  			tx := mockNormalTransaction("n1FkntVUMPAsESuCAAPK711omQk19JotBjM", "n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR", "0")
   180  			ctx, err := NewContext(mockBlockForLib(2000000), tx, contract, context)
   181  
   182  			// deploy and init.
   183  			engine := NewV8Engine(ctx)
   184  			engine.SetExecutionLimits(100000, 10000000)
   185  			_, err = engine.DeployAndInit(string(data), tt.sourceType, tt.initArgs)
   186  			assert.Nil(t, err)
   187  			engine.Dispose()
   188  
   189  			// call.
   190  			for _, fields := range tt.calls {
   191  				engine = NewV8Engine(ctx)
   192  				engine.SetExecutionLimits(100000, 10000000)
   193  				result, err := engine.Call(string(data), tt.sourceType, fields.function, fields.args)
   194  				fmt.Println("result", result)
   195  				assert.Equal(t, fields.result, result)
   196  				assert.Equal(t, fields.err, err)
   197  				engine.Dispose()
   198  			}
   199  		})
   200  	}
   201  }
   202  func TestTransferValueFromContracts(t *testing.T) {
   203  	type fields struct {
   204  		function string
   205  		args     string
   206  	}
   207  	tests := []struct {
   208  		contract   string
   209  		sourceType string
   210  		initArgs   string
   211  		calls      []fields
   212  		value      string
   213  		success    bool
   214  	}{
   215  		{
   216  			"./test/transfer_value_from_contract.js",
   217  			"js",
   218  			"",
   219  			[]fields{
   220  				{"transfer", "[\"n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17\"]"},
   221  			},
   222  			"100",
   223  			true,
   224  		},
   225  		{
   226  			"./test/transfer_value_from_contract.js",
   227  			"js",
   228  			"",
   229  			[]fields{
   230  				{"transfer", "[\"n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17\"]"},
   231  			},
   232  			"101",
   233  			false,
   234  		},
   235  	}
   236  
   237  	for _, tt := range tests {
   238  		t.Run(tt.contract, func(t *testing.T) {
   239  			data, err := ioutil.ReadFile(tt.contract)
   240  			assert.Nil(t, err, "contract path read error")
   241  
   242  			mem, _ := storage.NewMemoryStorage()
   243  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
   244  
   245  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
   246  			assert.Nil(t, err)
   247  			owner.AddBalance(newUint128FromIntWrapper(10000000))
   248  			addr, err := core.NewContractAddressFromData([]byte("n1FkntVUMPAsESuCAAPK711omQk19JotBjM"), byteutils.FromUint64(1))
   249  			assert.Nil(t, err)
   250  			contract, err := context.CreateContractAccount(addr.Bytes(), nil, nil)
   251  			assert.Nil(t, err)
   252  
   253  			contract.AddBalance(newUint128FromIntWrapper(100))
   254  			mockTx := mockNormalTransaction("n1FkntVUMPAsESuCAAPK711omQk19JotBjM", "n1FkntVUMPAsESuCAAPK711omQk19JotBjM", tt.value)
   255  			ctx, err := NewContext(mockBlock(), mockTx, contract, context)
   256  
   257  			// deploy and init.
   258  			engine := NewV8Engine(ctx)
   259  			engine.SetExecutionLimits(1000, 10000000)
   260  			_, err = engine.DeployAndInit(string(data), tt.sourceType, tt.initArgs)
   261  			assert.Nil(t, err)
   262  			engine.Dispose()
   263  
   264  			// call.
   265  			for _, fields := range tt.calls {
   266  				engine = NewV8Engine(ctx)
   267  				engine.SetExecutionLimits(10000, 10000000)
   268  				result, err := engine.Call(string(data), tt.sourceType, fields.function, fields.args)
   269  				if tt.success {
   270  					assert.Equal(t, result, "\""+fmt.Sprint(tt.value)+"\"")
   271  					assert.Nil(t, err)
   272  				} else {
   273  					assert.NotNil(t, err)
   274  				}
   275  				engine.Dispose()
   276  			}
   277  		})
   278  	}
   279  }