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 }