github.com/igggame/nebulas-go@v2.1.0+incompatible/nebtestkit/cases/contract/contract.feature.accept.test.js (about)

     1  'use strict';
     2  
     3  var sleep = require('system-sleep');
     4  var FS = require('fs');
     5  var expect = require('chai').expect;
     6  var BigNumber = require('bignumber.js');
     7  var HttpRequest = require('../../node-request');
     8  var TestnetConfig = require('../testnet_config');
     9  var Wallet = require('nebulas');
    10  
    11  var Account = Wallet.Account;
    12  var Transaction = Wallet.Transaction;
    13  var env = process.argv.splice(2)[1];
    14  var testnetConfig = new TestnetConfig(env);
    15  var originSource = testnetConfig.sourceAccount;
    16  var ChainID = testnetConfig.ChainId;
    17  var coinbase = testnetConfig.coinbase;
    18  var neb = new Wallet.Neb();
    19  neb.setRequest(new HttpRequest(testnetConfig.apiEndPoint));
    20  
    21  
    22  var deploy, from, contractAddr, source, fromState, coinState;
    23  var caseIndex = 0, lastnonce = 0;
    24  
    25  function prepareSource(done) {
    26      console.log("originSource address: " + originSource.getAddressString());
    27      neb.api.getAccountState(originSource.getAddressString()).then(function (resp) {
    28          console.log("prepare source account state:" + JSON.stringify(resp));
    29          var nonce = parseInt(resp.nonce);
    30  
    31          source = Account.NewAccount();
    32  
    33          var tx = new Transaction(ChainID, originSource, source, neb.nasToBasic(1000), nonce + 1, "1000000", "200000");
    34          tx.signTransaction();
    35  
    36          console.log("cliam source tx:", tx.toString());
    37  
    38          return neb.api.sendRawTransaction(tx.toProtoString());
    39      }).then(function (resp) {
    40          console.log("send Raw Tx:" + JSON.stringify(resp));
    41          expect(resp).to.be.have.property('txhash');
    42          checkTransaction(resp.txhash, 0, function (receipt) {
    43              console.log("tx receipt : " + JSON.stringify(receipt));
    44              expect(receipt).to.be.have.property('status').equal(1);
    45  
    46              done();
    47          });
    48      }).catch(function (err) {
    49          done(err);
    50      });
    51  }
    52  
    53  function cliamTokens(accounts, values, done) {
    54      for (var i = 0; i < accounts.length; i++) {
    55          console.log("acc:"+accounts[i].getAddressString()+" value:"+values[i]);
    56          sendTransaction(source, accounts[i], values[i], ++lastnonce);
    57          sleep(30);
    58      }
    59      checkCliamTokens(done);
    60  }
    61  
    62  
    63  function sendTransaction(from, address, value, nonce) {
    64      var transaction = new Transaction(ChainID, from, address, value, nonce, "1000000", "200000");
    65      transaction.signTransaction();
    66      var rawTx = transaction.toProtoString();
    67      neb.api.sendRawTransaction(rawTx).then(function (resp) {
    68          console.log("send raw transaction resp:" + JSON.stringify(resp));
    69      });
    70  }
    71  
    72  function checkCliamTokens(done) {
    73      var intervalAccount = setInterval(function () {
    74          neb.api.getAccountState(source.getAddressString()).then(function (resp) {
    75              // console.log("master accountState resp:" + JSON.stringify(resp));
    76              var nonce = parseInt(resp.nonce);
    77              console.log("check cliam tokens nonce:", lastnonce);
    78  
    79              if (lastnonce <= nonce){
    80                  console.log("cliam tokens success");
    81                  clearInterval(intervalAccount);
    82                  done();
    83              }
    84          });
    85      }, 2000);
    86  }
    87  
    88  function checkTransaction(txhash, retry, done){
    89  
    90      var maxRetry = 45;
    91  
    92      // contract status and get contract_address
    93      var interval = setTimeout(function () {
    94          neb.api.getTransactionReceipt(txhash).then(function (resp) {
    95              retry++;
    96  
    97              console.log("check transaction status:" + resp.status);
    98              if(resp.status && resp.status === 1) {
    99                  // clearInterval(interval);
   100  
   101                  if (resp.contract_address) {
   102                      console.log("deploy private key:" + deploy.getPrivateKeyString());
   103                      console.log("deploy address:" + deploy.getAddressString());
   104                      console.log("deploy contract address:" + resp.contract_address);
   105  
   106                      contractAddr = resp.contract_address;
   107                  }
   108  
   109                  done(resp);
   110              } else if (resp.status && resp.status === 2) {
   111                  if (retry > maxRetry) {
   112                      console.log("check transaction time out");
   113                      // clearInterval(interval);
   114                      done(resp);
   115                  } else {
   116                      checkTransaction(txhash, retry++, done);
   117                  }
   118              } else {
   119                  // clearInterval(interval);
   120                  console.log("transaction execution failed");
   121                  done(resp);
   122              }
   123          }).catch(function (err) {
   124              retry++;
   125              console.log("check transaction not found retry " + retry);
   126              if (retry > maxRetry) {
   127                  console.log(JSON.stringify(err.error));
   128                  // clearInterval(interval);
   129                  done(err);
   130              } else {
   131                  checkTransaction(txhash, retry++, done);
   132              }
   133          });
   134  
   135      }, 2000);
   136  }
   137  
   138  
   139  function deployContract(done, caseGroup) {
   140      console.log("start deploying contract: " + caseGroup.groupname);
   141  
   142      neb.api.getAccountState(source.getAddressString()).then(function (resp) {
   143          console.log("source account state:" + JSON.stringify(resp));
   144  
   145          var accounts = new Array();
   146          var values = new Array();
   147          deploy = Account.NewAccount();
   148          accounts.push(deploy);
   149          values.push(neb.nasToBasic(1));
   150  
   151          from = Account.NewAccount();
   152          accounts.push(from);
   153          var fromBalance = (typeof caseGroup.fromBalance === "undefined") ? neb.nasToBasic(1) : caseGroup.fromBalance;
   154          values.push(fromBalance);
   155  
   156          cliamTokens(accounts, values, () => {
   157              try {
   158                  var source = FS.readFileSync("../../../nf/nvm/test/" + caseGroup.filename, "utf-8");
   159                  var contract = {
   160                      "source": source,
   161                      "sourceType": caseGroup.type,
   162                      "args": ""
   163                  };
   164              
   165                  var tx = new Transaction(testnetConfig.ChainId, deploy, deploy, "0", 1, "10000000", "2000000", contract);
   166                  tx.signTransaction();
   167                  var rawTx = tx.toProtoString();
   168              
   169                  // console.log("contract:" + rawTx);
   170                  neb.api.sendRawTransaction(rawTx).then(function (resp) {
   171                      console.log("deploy contract " + caseGroup.groupname + " return: " + JSON.stringify(resp));
   172              
   173                      checkTransaction(resp.txhash, 0, (ret) => {
   174                          if (ret.status && ret.status === 1) {
   175                              done();
   176                          } else {
   177                              done(ret);
   178                          }
   179                      });
   180                  });
   181              } catch (err) {
   182                  done(err);
   183              };
   184          });
   185  
   186      }).catch (err => done(err));
   187  }
   188  
   189  function testBinary(testInput, testExpect, done) {
   190      var fromAcc = (typeof testInput.from === "undefined") ? from : testInput.from;
   191      var to = (typeof testInput.to === "undefined") ? Account.fromAddress(contractAddr) : testInput.to;
   192  
   193      var fromBalanceBefore, toBalanceBefore;
   194  
   195      neb.api.getAccountState(to.getAddressString()).then(function (resp) {
   196          console.log("contractAddr state before: " + JSON.stringify(resp));
   197          toBalanceBefore = resp.balance;
   198          return neb.api.getAccountState(from.getAddressString());
   199      }).then(resp => {
   200          fromState = resp;
   201          fromBalanceBefore = resp.balanece;
   202          console.log("from state before: ", JSON.stringify(resp));
   203          return neb.api.getAccountState(coinbase);
   204      }).then(function (resp) {
   205          console.log("coin state before: ", JSON.stringify(resp));
   206          coinState = resp;
   207  
   208          var tx = new Transaction(ChainID, fromAcc, to, testInput.value, parseInt(fromState.nonce) + testInput.nonce, testInput.gasPrice, testInput.gasLimit);
   209          tx.from.address = fromAcc.address;
   210          tx.to.address = to.address;
   211          tx.gasPrice = new BigNumber(testInput.gasPrice);
   212          tx.gasLimit = new BigNumber(testInput.gasLimit);
   213          tx.signTransaction();
   214          console.log("binary tx raw before send: ", tx.toString());
   215          return neb.api.sendRawTransaction(tx.toProtoString());
   216      }).then(function (rawResp) {
   217          console.log("send Raw Tx return:" + JSON.stringify(rawResp));
   218          expect(rawResp).to.be.have.property('txhash');
   219  
   220          checkTransaction(rawResp.txhash, 0, function (receipt) {
   221              console.log("tx receipt : " + JSON.stringify(receipt));
   222              try {
   223                  expect(receipt).to.not.be.a('undefined');
   224                  if (true === testExpect.canExcuteTx) {
   225                      expect(receipt).to.be.have.property('status').equal(1);
   226                  } else {
   227                      expect(receipt).to.be.have.property('status').equal(0);
   228                  }
   229  
   230                  neb.api.getAccountState(receipt.from).then(function (state) {
   231  
   232                      console.log("from state after: " + JSON.stringify(state));
   233                      // expect(state.balance).to.equal(testExpect.fromBalanceAfterTx);
   234                      return neb.api.getAccountState(contractAddr);
   235                  }).then(function (state) {
   236  
   237                      console.log("contractAddr state after: " + JSON.stringify(state));
   238                      var change = new BigNumber(state.balance).minus(new BigNumber(toBalanceBefore));
   239                      // expect(change.toString()).to.equal(testExpect.toBalanceChange);
   240                      return neb.api.getAccountState(coinbase);
   241                  }).then(function (state) {
   242  
   243                      console.log("get coinbase account state before tx:" + JSON.stringify(coinState));
   244                      console.log("get coinbase account state after tx:" + JSON.stringify(state));
   245                      var reward = new BigNumber(state.balance).sub(coinState.balance);
   246                      reward = reward.mod(new BigNumber(1.42694).mul(new BigNumber(10).pow(18)));
   247                      // The transaction should be only
   248                      // expect(reward.toString()).to.equal(testExpect.transferReward);
   249                      console.log("coinbase reward: " + reward.toString());
   250                      if (receipt.gasUsed) {
   251                          var txCost = new BigNumber(receipt.gasUsed).mul(receipt.gasPrice).toString(10);
   252                          // expect(txCost).to.equal(testExpect.transferReward);
   253                          console.log("tx cost gas: " + txCost.toString());
   254                      }
   255  
   256                      return neb.api.getEventsByHash(receipt.hash);
   257                  }).then(function (events) {
   258                      for (var i = 0; i < events.events.length; i++) {
   259                          var event = events.events[i];
   260                          //console.log("tx event:", JSON.stringify(event,null,'\t'));
   261                          console.log("tx event:", event.data);
   262                          if (event.topic === "chain.transactionResult") {
   263                              var result = JSON.parse(event.data);
   264                              expect(result.status).to.equal(testExpect.status);
   265  
   266                              if (testExpect.hasOwnProperty("eventErr")){
   267                                  console.log("Event error checked.");
   268                                  expect(result.error).to.equal(testExpect.eventErr);
   269                              }
   270                          }
   271                      }
   272                      done();
   273                  }).catch(function (err) {
   274                      console.log("exe tx err:", err);
   275                      done(err);
   276                  });
   277              } catch (err) {
   278                  console.log("submit tx err:", err.message);
   279                  done(err);
   280              }
   281          });
   282      }).catch(function (err) {
   283          console.log("send tx err", err);
   284          if (err.error && err.error.error && testExpect.eventErr) {
   285              try {
   286                  expect(err.error.error).to.equal(testExpect.eventErr)
   287                  done();
   288              } catch (err) {
   289                  done(err);
   290              }
   291              return;
   292          }
   293          done(err);
   294      });
   295  }
   296  
   297  var testCaseGroups = [];
   298  var caseGroup = {
   299      "filename": "contract_accept_func_with_args.js",
   300      "type": "js",
   301      "groupname": "case group 0: accept takes some args with execution error",
   302      "groupIndex": 0,
   303  
   304      cases: [
   305          {
   306              "name": "0-1. value = 0, invalid args",
   307              "testInput": {
   308                  // from: from, 
   309                  // to: contractAddr,
   310                  value: "0",
   311                  nonce: 1, 
   312                  gasPrice: 1000000,
   313                  gasLimit: 2000000
   314              },
   315              "testExpect": {
   316                  canExcuteTx: false,
   317                  toBalanceChange: "0",
   318                  status: 0,
   319                  eventErr: "Binary: BigNumber Error: plus() not a number: undefined"
   320              }
   321          }
   322      ]
   323  };
   324  testCaseGroups.push(caseGroup);
   325  
   326  caseGroup = {
   327      "filename": "contract_accept_func_with_args_2.js",
   328      "type": "js",
   329      "groupname": "case group 1: accept takes some args witchout execution error",
   330      "groupIndex": 1,
   331  
   332      cases: [
   333          {
   334              "name": "1-1. value = 0",
   335              "testInput": {
   336                  // from: from, 
   337                  // to: contractAddr,
   338                  value: "0",
   339                  nonce: 1, 
   340                  gasPrice: 1000000,
   341                  gasLimit: 2000000
   342              },
   343              "testExpect": {
   344                  canExcuteTx: true,
   345                  toBalanceChange: "0",
   346                  status: 1
   347              }
   348          },
   349  
   350          {
   351              "name": "1-2. value > 0",
   352              "testInput": {
   353                  // from: from, 
   354                  // to: contractAddr,
   355                  value: "100",
   356                  nonce: 1, 
   357                  gasPrice: 1000000,
   358                  gasLimit: 2000000
   359              },
   360              "testExpect": {
   361                  canExcuteTx: true,
   362                  toBalanceChange: "100",
   363                  status: 1
   364              }
   365          }
   366      ]
   367  };
   368  testCaseGroups.push(caseGroup);
   369  
   370  caseGroup = {
   371      "filename": "bank_vault_contract.js",
   372      "type": "js",
   373      "groupname": "case group 2: bankvault without accept func",
   374      "groupIndex": 2,
   375  
   376      cases: [
   377          {
   378              "name": "2-1. value > 0",
   379              "testInput": {
   380                  // from: from, 
   381                  // to: contractAddr,
   382                  value: "100",
   383                  nonce: 1, 
   384                  gasPrice: 1000000,
   385                  gasLimit: 2000000
   386              },
   387              "testExpect": {
   388                  canExcuteTx: false,
   389                  toBalanceChange: "0",
   390                  status: 0,
   391                  eventErr: "Binary: TypeError: Cannot read property 'apply' of undefined"
   392              }
   393          }
   394      ]
   395  };
   396  testCaseGroups.push(caseGroup);
   397  
   398  caseGroup = {
   399      "filename": "contract_accept_func_standard.js",
   400      "type": "js",
   401      "groupname": "case group 3: bankvault with standard accept func",
   402      "groupIndex": 3,
   403  
   404      cases: [
   405          {
   406              "name": "3-1. value > 0",
   407              "testInput": {
   408                  // from: from, 
   409                  // to: contractAddr,
   410                  value: "100",
   411                  nonce: 1, 
   412                  gasPrice: 1000000,
   413                  gasLimit: 2000000
   414              },
   415              "testExpect": {
   416                  canExcuteTx: true,
   417                  toBalanceChange: "100",
   418                  status: 1
   419              }
   420          }
   421      ]
   422  };
   423  testCaseGroups.push(caseGroup);
   424  
   425  describe('accept func test', () => {
   426  
   427      before(done => prepareSource(done));
   428  
   429      for (var i = 0; i < testCaseGroups.length; i++) {
   430  
   431          // if (i != 2) {continue;}         // selectively run tests
   432  
   433          let caseGroup = testCaseGroups[i];
   434          describe(caseGroup.groupname, () => {
   435              before(done => {
   436                  deployContract(done, caseGroup);
   437                  caseIndex = 0;
   438              });
   439  
   440              
   441              for (var j = 0; j < caseGroup.cases.length; j++) {
   442                  let testCase = caseGroup.cases[j];
   443                  it(testCase.name, done => {
   444                      console.log("===> running case: " + JSON.stringify(testCase));
   445                      testBinary(testCase.testInput, testCase.testExpect, done);
   446                  });
   447              }
   448  
   449              afterEach(() => {
   450                  caseIndex++;
   451                  console.log("case group: " + caseGroup.groupIndex + ", index: " + caseIndex);
   452              });
   453          });
   454      }
   455  });