First wokring tests set

This commit is contained in:
Kirill Fedoseev 2019-10-27 19:21:36 +03:00
parent 7aeaf94627
commit 13c0734691
15 changed files with 340 additions and 22 deletions

View File

@ -94,6 +94,11 @@ jobs:
name: "Stop dev environment"
command: docker kill ganache_side ganache_home
- bridge/save_ganache_data
- run:
name: "Prefund bnc addresses"
command: |
echo "FOREIGN_PRIVATE_KEY=$FOREIGN_PRIVATE_KEY" > ./src/test-services/.keys.$TARGET_NETWORK
cat ./tests/config.json | jq .users[].bncAddress | xargs -I {} ./src/test-services/binanceSend/run.sh {} 100 0.1
run_tests:
executor: bridge/node-dev
steps:
@ -107,17 +112,15 @@ jobs:
name: "Init tests environment"
command: |
./demo/start-environment.sh
echo "FOREIGN_PRIVATE_KEY=$FOREIGN_PRIVATE_KEY" > ./src/test-services/.keys.$TARGET_NETWORK
cat ./tests/config.json | jq .users[].bncAddress | xargs -I {} ./src/test-services/binanceSend/run.sh {} 100 0.1
N=1 ./demo/validator-demo.sh -d
N=2 ./demo/validator-demo.sh -d
N=3 ./demo/validator-demo.sh -d
- run:
name: "Wait until validator nodes are ready"
command: |
until curl -X GET http://localhost:5001 > /dev/null 2>&1; do sleep 1; done
until curl -X GET http://localhost:5002 > /dev/null 2>&1; do sleep 1; done
until curl -X GET http://localhost:5003 > /dev/null 2>&1; do sleep 1; done
docker run --network validator1_test_network --entrypoint ash appropriate/curl:latest -c "until curl -X GET http://proxy:8002/info > /dev/null 2>&1; do sleep 1; done"
docker run --network validator2_test_network --entrypoint ash appropriate/curl:latest -c "until curl -X GET http://proxy:8002/info > /dev/null 2>&1; do sleep 1; done"
docker run --network validator3_test_network --entrypoint ash appropriate/curl:latest -c "until curl -X GET http://proxy:8002/info > /dev/null 2>&1; do sleep 1; done"
- run:
name: "Build and prepare tests container"
command: |
@ -125,11 +128,16 @@ jobs:
docker create --rm -e HOME_RPC_URL --name tests tests $@
docker network connect blockchain_side tests
docker network connect blockchain_home tests
docker network connect validator1_test_network tests
docker network connect validator2_test_network tests
docker network connect validator3_test_network tests
environment:
HOME_RPC_URL: 'http://ganache_home:8545'
- run:
name: "Run tests"
command: docker start tests
command: |
docker start -a tests
docker cp "tests:/tests/results.xml" "./tests/results.xml"
workflows:
version: 2
main:

View File

@ -135,7 +135,7 @@ deploy_all() {
if [[ "$TARGET_NETWORK" == "development" ]]; then
if [[ "$(docker volume ls | grep ganache_side_db)" ]] || [[ "$(docker volume ls | grep ganache_home_db)" ]]; then
if [[ "$(docker volume ls | grep ganache_side_data)" ]] || [[ "$(docker volume ls | grep ganache_home_data)" ]]; then
echo "Restarting dev blockchain networks"
else
echo "Starting dev blockchain networks and deploying contracts"

3
tests/.mocharc.yml Normal file
View File

@ -0,0 +1,3 @@
reporter: spec
reporter-option:
- mochaFile=./results.xml

View File

@ -2,13 +2,15 @@ FROM node:10.16.0-alpine
WORKDIR /tests
RUN npm install -g mocha
RUN npm install -g mocha mocha-junit-reporter
RUN apk update && apk add libssl1.1 eudev-dev libressl-dev curl build-base python linux-headers libusb-dev
COPY ./package.json .
RUN npm install
COPY config.json ./
COPY config.json .mocharc.yml ./
COPY test ./test
ENTRYPOINT ["mocha"]

4
tests/init.sh Normal file → Executable file
View File

@ -1,11 +1,11 @@
#!/bin/bash
set -e
set -v
./demo/start-environment.sh
echo "FOREIGN_PRIVATE_KEY=$FOREIGN_PRIVATE_KEY" > ./src/test-services/.keys.$TARGET_NETWORK
cat ./tests/config.json | jq .users[].ethAddress | xargs -I {} ./src/test-services/ethereumSend/run.sh {} 100
cat ./tests/config.json | jq .users[].bncAddress | xargs -I {} ./src/test-services/binanceSend/run.sh {} 100 0.1
N=1 ./demo/validator-demo.sh -d

View File

@ -2,6 +2,9 @@
"name": "tests",
"version": "0.0.1",
"dependencies": {
"web3": "1.0.0-beta.55"
"ethers": "4.0.38",
"axios": "0.19.0",
"@binance-chain/javascript-sdk": "2.16.1",
"bignumber.js": "9.0.0"
}
}

View File

@ -1,8 +1,29 @@
#!/bin/bash
set -e
set -v
docker build -t tests ./tests
docker run --network blockchain_home --rm -e HOME_RPC_URL tests $@
set -a
source ./demo/validator1/.env.development
set +a
docker rm tests || true
docker create --name tests \
-e HOME_RPC_URL \
-e FOREIGN_URL \
-e HOME_BRIDGE_ADDRESS \
-e HOME_TOKEN_ADDRESS \
-e FOREIGN_PRIVATE_KEY \
-e FOREIGN_ASSET \
tests $@
docker network connect blockchain_home tests
docker network connect validator1_test_network tests
docker network connect validator2_test_network tests
docker network connect validator3_test_network tests
docker start -a tests || true
docker cp "tests:/tests/results.xml" "./tests/results.xml" || true
docker rm tests || true

51
tests/test/ethToBnc.js Normal file
View File

@ -0,0 +1,51 @@
const assert = require('assert')
const createUser = require('./utils/user')
const { getSequence } = require('./utils/bncController')
const { waitPromise, delay } = require('./utils/wait')
const usersConfig = require('../config').users
const { HOME_BRIDGE_ADDRESS } = process.env
module.exports = (foreignBridgeAddress) => {
describe('exchanges tokens in eth => bnc direction', function () {
let ethBalances
let bncBalances
let bncBridgeSequence
let users
before(async function () {
this.timeout(60000)
users = await usersConfig.seqMap(user => createUser(user.privateKey))
ethBalances = await Promise.all(users.map(user => user.getEthBalance()))
bncBalances = await users.seqMap(user => user.getBncBalance())
bncBridgeSequence = await getSequence(foreignBridgeAddress())
await Promise.all(users.map((user, i) => user.approveEth(HOME_BRIDGE_ADDRESS, 5 + i)))
})
it('should accept exchange requests', async function () {
this.timeout(60000)
await Promise.all(users.map((user, i) => user.exchangeEth(5 + i)))
const newEthBalances = await Promise.all(users.map(user => user.getEthBalance()))
for (let i = 0; i < 3; i++) {
assert(newEthBalances[i] === ethBalances[i] - 5 - i, `Balance of ${usersConfig[i].ethAddress} did not updated as expected`)
}
ethBalances = newEthBalances
})
it('should make exchange transaction on bnc side', async function () {
this.timeout(300000)
await waitPromise(() => getSequence(foreignBridgeAddress()), sequence => sequence === bncBridgeSequence + 1)
})
it('should make correct exchange transaction', async function () {
this.timeout(60000)
const newBncBalances = await Promise.all(users.map(user => user.getBncBalance()))
for (let i = 0; i < 3; i++) {
assert(newBncBalances[i] === bncBalances[i] + 5 + i, `Balance of ${usersConfig[i].bncAddress} did not updated as expected`)
}
bncBalances = newBncBalances
})
})
}

View File

@ -1,12 +1,32 @@
const Web3 = require('web3')
const { users } = require('../config')
const createController = require('./utils/proxyController')
const createUser = require('./utils/user')
const { waitPromise } = require('./utils/wait')
const web3 = new Web3(process.env.HOME_RPC_URL)
const testEthToBnc = require('./ethToBnc')
describe('check balance', function () {
it('should have correct balance', async function () {
const balance = await web3.eth.getBalance(users[0].ethAddress)
console.log(balance.toNumber())
return 0
const { FOREIGN_PRIVATE_KEY } = process.env
let user
let { getInfo } = createController(1)
let info
describe('generates initial epoch keys', function () {
before(async function () {
this.timeout(60000)
user = await createUser(FOREIGN_PRIVATE_KEY)
})
it('should generate keys in 2 min', async function () {
this.timeout(120000)
info = await waitPromise(getInfo, info => info.epoch === 1)
})
after(async function () {
this.timeout(60000)
await user.transferBnc(info.foreignBridgeAddress, 50, 0.1)
})
})
testEthToBnc(() => info.foreignBridgeAddress)

View File

@ -0,0 +1,42 @@
const Bnc = require('@binance-chain/javascript-sdk')
const { delay } = require('./wait')
const { FOREIGN_URL, FOREIGN_ASSET } = process.env
module.exports = async function main (privateKey) {
const client = new Bnc(FOREIGN_URL)
client.chooseNetwork('testnet')
await client.setPrivateKey(privateKey)
await client.initChain()
const from = client.getClientKeyAddress()
await delay(1000)
return {
transfer: async function (to, tokens, bnbs) {
const outputs = [{
to,
coins: []
}]
if (tokens) {
outputs[0].coins.push({
denom: FOREIGN_ASSET,
amount: tokens
})
}
if (bnbs) {
outputs[0].coins.push({
denom: 'BNB',
amount: bnbs
})
}
await client.multiSend(from, outputs, 'funding')
},
exchange: async function (to, value) {
await client.transfer(from, to, value.toString(), FOREIGN_ASSET, 'exchange')
}
}
}

View File

@ -0,0 +1,29 @@
const axios = require('axios')
const { FOREIGN_URL, FOREIGN_ASSET } = process.env
const bnc = axios.create({
baseURL: FOREIGN_URL,
timeout: 5000
})
module.exports = {
getBalance: async function (address) {
try {
const response = await bnc.get(`/api/v1/account/${address}`)
return parseFloat(response.data.balances.find(x => x.symbol === FOREIGN_ASSET).free)
} catch (e) {
return 0
}
},
getSequence: async function(address) {
try {
const response = await bnc.get(`/api/v1/account/${address}/sequence`)
return response.data.sequence
} catch (e) {
return 0
}
}
}

View File

@ -0,0 +1,24 @@
const ethers = require('ethers')
const { HOME_RPC_URL, HOME_TOKEN_ADDRESS, HOME_BRIDGE_ADDRESS } = process.env
const abiToken = [
'function balanceOf(address account) view returns (uint)',
'function transfer(address to, uint value)',
'function approve(address to, uint value)',
'function allowance(address owner, address spender) view returns (uint)'
]
const abiBridge = [
'function exchange(uint value)'
]
const provider = new ethers.providers.JsonRpcProvider(HOME_RPC_URL)
const tokenContract = new ethers.Contract(HOME_TOKEN_ADDRESS, abiToken, provider)
const bridgeContract = new ethers.Contract(HOME_BRIDGE_ADDRESS, abiBridge, provider)
module.exports = {
tokenContract,
bridgeContract,
provider
}

View File

@ -0,0 +1,31 @@
const axios = require('axios')
module.exports = function (validatorId) {
const url = `http://validator${validatorId}_proxy_1:8002/`
const proxy = axios.create({
baseURL: url,
timeout: 5000
})
return {
getInfo: async function () {
return (await proxy.get('/info')).data
},
voteStartVoting: async function () {
return (await proxy.get('/vote/startVoting')).data
},
voteStartKeygen: async function () {
return (await proxy.get('/vote/startKeygen')).data
},
voteAddValidator: async function (validatorAddress) {
return (await proxy.get(`/vote/addValidator/${validatorAddress}`)).data
},
voteRemoveValidator: async function (validatorAddress) {
return (await proxy.get(`/vote/removeValidator/${validatorAddress}`)).data
},
voteChangeThreshold: async function (threshold) {
return (await proxy.get(`/vote/changeThreshold/${threshold}`)).data
}
}
}

59
tests/test/utils/user.js Normal file
View File

@ -0,0 +1,59 @@
const ethers = require('ethers')
const BN = require('bignumber.js')
const { getAddressFromPrivateKey } = require('@binance-chain/javascript-sdk/lib/crypto')
const createBncClient = require('./bncClient')
const { getBalance } = require('./bncController')
const { tokenContract, bridgeContract, provider } = require('./homeContracts')
const { delay } = require('./wait')
const txOptions = {
gasLimit: 200000
}
module.exports = async function (privateKey) {
const wallet = new ethers.Wallet(privateKey, provider)
const ethAddress = wallet.address
const bncAddress = getAddressFromPrivateKey(privateKey)
const token = tokenContract.connect(wallet)
const bridge = bridgeContract.connect(wallet)
const bncClient = await createBncClient(privateKey)
return {
getEthBalance: async function () {
const balance = await token.balanceOf(ethAddress)
return parseFloat(new BN(balance).dividedBy(10 ** 18).toFixed(8, 3))
},
transferEth: async function (to, value) {
const tx = await token.transfer(to, '0x' + (new BN(value).multipliedBy(10 ** 18).toString(16)), txOptions)
await tx.wait()
},
approveEth: async function (to, value) {
console.log('approving', to, value)
const tx = await token.approve(to, '0x' + (new BN(value).multipliedBy(10 ** 18).toString(16)), txOptions)
console.log('sent', tx)
await tx.wait()
console.log('done')
console.log(await token.allowance(ethAddress, to))
},
exchangeEth: async function (value) {
console.log(value)
const tx = await bridge.exchange('0x' + (new BN(value).multipliedBy(10 ** 18).toString(16)), txOptions)
console.log(tx)
await tx.wait()
console.log('done')
},
getBncBalance: async function () {
const balance = await getBalance(bncAddress)
await delay(1000)
return balance
},
transferBnc: async function (bridgeAddress, tokens, bnbs) {
return await bncClient.transfer(bridgeAddress, tokens, bnbs)
},
exchangeBnc: async function (bridgeAddress, value) {
return await bncClient.exchange(bridgeAddress, value)
}
}
}

25
tests/test/utils/wait.js Normal file
View File

@ -0,0 +1,25 @@
async function delay(ms) {
await new Promise(res => setTimeout(res, ms))
}
async function waitPromise (getPromise, checker) {
do {
const result = await getPromise()
if (checker(result))
return result
await delay(1000)
} while (true)
}
Array.prototype.seqMap = async function (transition) {
const results = []
for (let i = 0; i < this.length; i++) {
results[i] = await transition(this[i])
}
return results
}
module.exports = {
waitPromise,
delay
}