Skip to content

Commit

Permalink
Merge pull request #30 from devintegral4/autotest_addition
Browse files Browse the repository at this point in the history
Integration tests addition
  • Loading branch information
devintegral3 committed Mar 19, 2020
2 parents 463d8b8 + 052cdbe commit cdfe552
Show file tree
Hide file tree
Showing 49 changed files with 425,916 additions and 349 deletions.
2 changes: 1 addition & 1 deletion contracts/sfc/Staker.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity ^0.5;
pragma solidity ^0.5.0;

import "./SafeMath.sol";
import "../ownership/Ownable.sol";
Expand Down
1 change: 1 addition & 0 deletions integration_tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
35 changes: 35 additions & 0 deletions integration_tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
### How to start local tests
Clone this repository and run ```npm install```
Then run fakenet lachesis node with rpc turned on:
```bash
./build/lachesis --fakenet=1/1 --rpc --rpcapi="eth,debug,admin,web3,personal,net,txpool,ftm,sfc"
```
Now you can run local tests with:
```bash
node testing.js
```

If a host/port of your rpc is not default, you can specify it with flags ```-h``` and ```-p``` respectively:
```bash
node testing.js -h "127.0.0.1" -p 18545
```
You can also set a contract address manualy with ```-c``` flag
If you run lachesis with a single validator, you will probably also need to increase default stake value in code (for testing purpose).
You can find it inside go-lachesis/cmd/lachesis/fake.go. For example:
```golang
vaccs = genesis.FakeValidators(validatorsNum, utils.ToFtm(1e10), utils.ToFtm(3175000 * 10))
```

You can also reduce cfg.MaxEpochBlocks value, this will speed testing up (variable is placed inside /go-lachesis/lachesis/config.go file, FakeNetDagConfig func). For example you can set it to 20 blocks.
```golang
cfg.MaxEpochBlocks = 20
```
### How to start staging testing
A staging testing cases run via RPC calls, so you have to make sure that "--rpc" flag is passed to an app and that all namespaces are turned on (you can just use an example above with --rpc --rpcapi="eth,debug,admin,web3,personal,net,txpool,ftm,sfc" flags).
If rpc is turned on and nodes are running, it is possible to start testing.
To run tests properly, you will have to provide a payer - an account with a huge amount of available resources. A payer should be defined inside config.json. You can try to use a default config.json with a default payer for a staging testing, as it doesn't change realy often.
To run tests with a payer you just have to provide "--payer" flag, and a payer info will be taken from config.

```bash
node testing.js --payer
```
7 changes: 7 additions & 0 deletions integration_tests/abi.js

Large diffs are not rendered by default.

100,001 changes: 100,001 additions & 0 deletions integration_tests/accounts.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions integration_tests/bin.js

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions integration_tests/cli_tests.js

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions integration_tests/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"payer": {
"keyObject": {"address":"95f30ec61da14a8b3abc24bb11eebcf58f9f0cf3","crypto":{"cipher":"aes-128-ctr","ciphertext":"30f6235d561c44538eb6c234b1e429c56a3650a3b04c4b0aa5905533d7c82922","cipherparams":{"iv":"4ab0baf8eef69a38b2f5069b4b0582c0"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"a09cc7d83a86b42087e7cfe34566206daf5956f8cffee2803175739f2790cef3"},"mac":"f8b64f2824acc98f2e551de0e696717e5dcf55bedf105269c022bbf0281c82b5"},"id":"abbeda74-c324-4120-9d99-efa3236ead00", "version":3},
"privateKey": "343ba3ed7da835da945f9cbd784e62e1c329737c1b33b262e38a53501021af44",
"address": "0x95f30ec61da14a8b3abc24bb11eebcf58f9f0cf3"
}
}
25 changes: 25 additions & 0 deletions integration_tests/contracts.json

Large diffs are not rendered by default.

654 changes: 654 additions & 0 deletions integration_tests/defaultTests.js

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions integration_tests/format_test_accs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const fs = require("fs");

// it is assumed that test_accs.json from "go-lachesis/docker" are used.
// a json file must be served in a propper way.
// it doesnt work exactly well for now, needs to be updated
const pathToTestAccs = "./test_accs.json";
let file = fs.readFileSync(pathToTestAccs);
let str = file.toString();
let r = /,"0x(.*?)": /g;

let newStr = str
newStr = str.replace(r, str => {
let x = "},{\"address\":" + str.slice(1, str.length-2) + ", \"props\": ";
return x;
})

fs.writeFileSync('./accounts.json', newStr);

//solc_5.11 --bin-runtime --allow-paths ~/repos/work/solidity/fantom_sfc_v1.1/contracts/ownership/ --combined-json abi,asm,ast,bin,bin-runtime,devdoc,interface,opcodes,srcmap,srcmap-runtime,userdoc contracts/sfc/Staker.sol > contracts.json
13 changes: 13 additions & 0 deletions integration_tests/keyth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var keythereum = require("keythereum-pure-js");
var datadir = "~/.lachesis/";
var address= "0x19eb4c98009be5d8bcbc07520fb1871a8e348674";
const password = "123456";
var datadir = "/home/masurk/.lachesis/fakenet-1/";
var keyObject = keythereum.importFromFile(address, datadir);
var pk1 = keythereum.recover(password, keyObject);
console.log("pk1", pk1)
keyObject = {"address":"95f30ec61da14a8b3abc24bb11eebcf58f9f0cf3","crypto":{"cipher":"aes-128-ctr","ciphertext":"30f6235d561c44538eb6c234b1e429c56a3650a3b04c4b0aa5905533d7c82922","cipherparams":{"iv":"4ab0baf8eef69a38b2f5069b4b0582c0"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"a09cc7d83a86b42087e7cfe34566206daf5956f8cffee2803175739f2790cef3"},"mac":"f8b64f2824acc98f2e551de0e696717e5dcf55bedf105269c022bbf0281c82b5"},"id":"abbeda74-c324-4120-9d99-efa3236ead00","version":3};
var pk2 = keythereum.recover(password, keyObject);
console.log(privateKey.toString('hex'));
console.log("pk2", pk1)
//343ba3ed7da835da945f9cbd784e62e1c329737c1b33b262e38a53501021af44
141 changes: 141 additions & 0 deletions integration_tests/lachesis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
const Web3 = require('web3');
const LachesisRpc = require('./lachesisRpc');
const SfcTransactions = require('./sfcTransactions');
const BN = Web3.utils.BN;

class lachesis {
constructor(web3, sfc, contractAddress, upgradabilityProxy, txStorage) {
this.contractAddress = contractAddress;
this.web3 = web3;
this.txStorage = txStorage;
this.upgradabilityProxy = upgradabilityProxy;
this.sfc = sfc;
this.transactions = new SfcTransactions.TransactionHandler(web3, this.sfc, this.contractAddress, this.txStorage);
this.rpc = new LachesisRpc.rpc();
}

// returns first transaction within N blocks or null if no transactions found
async findLastTransaction(maxBlocksToInspect, newContractAddress) {
let latestBlock = await this.rpc.getLatestBlock();
let latestBlockNumber = new BN(this.web3.utils.hexToNumber(latestBlock.data.result.number));
let prevBlockNum = latestBlockNumber;

// let blockNum = latestBlockNumber;
let txs = await this.transactionFromBlock(latestBlock);
if (txs && txs.length != 0) {
// console.log("txs 26", txs);
return txs;
}

for (let i=0; i<maxBlocksToInspect; i++) {
prevBlockNum = latestBlockNumber.sub(new BN(1));
let block = await this.rpc.getLatestBlock(prevBlockNum);
let txs = await this.transactionFromBlock(block);
// console.log("txs", txs);
if (txs && txs.length != 0) {
// console.log("txs 35", txs);
return txs;
}
}

console.log("no transactions found within", maxBlocksToInspect, "blocks");
}

async transactionFromBlock(block) {
return block.data.result.transactions;
}

async upgradeTo(accountFrom, address) {
// console.log("typeof accountFrom", typeof accountFrom);
const nonce = await this.web3.eth.getTransactionCount(accountFrom.address);
const gasPrice = await this.web3.eth.getGasPrice();
const to = this.contractAddress;
const memo = this.upgradabilityProxy.methods.upgradeTo(address).encodeABI();

const rawTx = {
from: accountFrom.address,
to: to,
gasPrice: this.web3.utils.toHex(gasPrice),
nonce: this.web3.utils.toHex(nonce),
data: memo
};
let estimatedGas = await this.estimateGas(rawTx);
rawTx.gasLimit = this.web3.utils.toHex(estimatedGas);
let signedTx = await this.web3.eth.accounts.signTransaction(rawTx, accountFrom.privateKey);
return this.web3.eth.sendSignedTransaction(signedTx.rawTransaction, function(err, hash) {
if (err)
throw(err);
console.log("tx sendSignedTransaction hash:", hash);
});
}

async forceNewEpoch(accountFrom) {
const turnLogsOff = true;
console.log("forcing new epoch");
const metadata = "0x"
let currEpochRpcRes = await this.rpc.currentEpoch();
const startEpoch = this.web3.utils.hexToNumber(currEpochRpcRes.result);
let currentEpoch = startEpoch;
console.log("current epoch (at the beginning)", currentEpoch);
while (true) {
await this.transactions.updateStakerMetadata(accountFrom, metadata, turnLogsOff);
currEpochRpcRes = await this.rpc.currentEpoch();
currentEpoch = this.web3.utils.hexToNumber(currEpochRpcRes.result);
if (currentEpoch !== startEpoch) {
console.log("current epoch (at the end)", currentEpoch);
return;
}
}
}

async proxyImplementation(from) {
return new Promise(resolve => {
this.upgradabilityProxy.methods.implementation().call({from}, function (error, result) {
if (!error) {
resolve(result);
} else {
console.log('getStakerId err', error);
}
});
});
}

async updateContract(accountFrom, data) {
console.log("prepare to updateContract");
const nonce = await this.web3.eth.getTransactionCount(accountFrom.address);
const gasPrice = await this.web3.eth.getGasPrice();
const to = null;

const rawTx = {
from: accountFrom.address,
gasPrice: this.web3.utils.toHex(gasPrice),
nonce: this.web3.utils.toHex(nonce),
data: data
};

let estimatedGas = await this.estimateGas(rawTx);
rawTx.gasLimit = this.web3.utils.toHex(estimatedGas);
let tx = await this.web3.eth.accounts.signTransaction(rawTx, accountFrom.privateKey);
await this.web3.eth.sendSignedTransaction(tx.rawTransaction, (err, txHash) => {
if (err) {
console.log("updateContract err", err);
}
}); // txHash expected to be null. so we need to get last tx hash and read new contract address


};

async estimateGas(rawTx) {
let estimateGas;
await this.web3.eth.estimateGas(rawTx, (err, gas) => {
if (err)
throw(err);

estimateGas = gas;
});

return estimateGas;
};
}

module.exports.lachesis = lachesis;
78 changes: 78 additions & 0 deletions integration_tests/lachesisRpc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
const axios = require('axios');

class rpc {
async lachesis() {
let res = await axios(this.post_config({"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}));
console.log(res.data);
/*
{ jsonrpc: '2.0',
id: 57,
result: 'go-lachesis/v1.9.8-stable/linux-amd64/go1.13.3' }
*/

res = await axios(this.post_config({"jsonrpc":"2.0","method":"net_version","params":[],"id":67}));
console.log(res.data);

res = await axios(this.post_config({"jsonrpc":"2.0","method":"eth_getBalance","params":["0x7f9d1dbaf84d827b0840e38f555a490969978d20", "latest"],"id":1}));
console.log(res.data);


res = await axios(this.post_config({"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["0xf865808609184e72a00082271094d6a37423be930019b8cfea57be049329f3119a3d800026a022ee12db5a53b2a43d79c3d5b30f26287817a785da4be80b85ea368c746b2e0fa06e7178582d58eb80e407062c4afc4f4634e2908ef1b874f36b93b94093902f66"],"id":1}));
console.log(res.data)
}

async getTxPoolContent() {
let req = {"jsonrpc":"2.0","method":"txpool_content","params":[],"id":1};
let res = await axios(this.post_config(req));
return res;
}

async getLatestBlock() {
let req = {"jsonrpc":"2.0","method":"ftm_getBlockByNumber","params":["latest", false],"id":1};
let res = await axios(this.post_config(req));
return res;
}

async getBlockByNumber(num) {
let req = {"jsonrpc":"2.0","method":"ftm_getBlockByNumber","params":[num.toString(), false],"id":1};
let res = await axios(this.post_config(req));
return res;
}

async coinbase() {
const req = {"jsonrpc":"2.0","method":"eth_coinbase","id":1};
const res = await axios(this.post_config(req));
if (res.data && res.data.error) {
console.log("request error:", res.data.error);
}
return res.data.result;
}

async currentEpoch() {
const req = `{"jsonrpc":"2.0","method":"ftm_currentEpoch","id":1}`
const res = await axios(this.post_config(req));
return res.data
}

async getTransactionReceipt(hash) {
const req = {
"jsonrpc":"2.0",
"method":"ftm_getTransactionReceipt",
"params":[hash],
"id":1
};
const res = await axios(this.post_config(req));
return res.data;
}

post_config(data) {
return {
method: 'post',
url: 'http://localhost:18545/',
data: data,
headers: {'content-type':'application/json'}
}
}
}

module.exports.rpc = rpc;
Loading

0 comments on commit cdfe552

Please sign in to comment.