From 0219ca5e8a0c2c8754b73bb1fe118c423642033a Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Wed, 10 Feb 2021 08:46:10 +0000 Subject: [PATCH] tests: add transfer load script --- --- a/tests/package.json +++ b/tests/package.json @@ -20,6 +20,7 @@ "scripts": { "test": "mocha --timeout 9999999 -r ts-node/register ./**/*.test.ts", "load": "mocha --timeout 9999999 -r ts-node/register ./**/*.load.ts", + "loadTransfer": "ts-node src/transfer.nload.ts", "testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts", "testSetSchemaVersion": "mocha --timeout 9999999 -r ts-node/register ./**/setSchemaVersion.test.ts", "testSetVariableMetaData": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetaData.test.ts", --- a/tests/src/transfer.load.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { ApiPromise } from "@polkadot/api"; -import { IKeyringPair } from '@polkadot/types/types'; -import privateKey from "./substrate/privateKey"; -import usingApi, { submitTransactionAsync } from "./substrate/substrate-api"; -import waitNewBlocks from "./substrate/wait-new-blocks"; -import { findUnusedAddresses } from "./util/helpers"; -import * as cluster from 'cluster'; -import os from 'os'; - -// Innacurate transfer fee -const FEE = 10n ** 8n; - -let counters: { [key: string]: number } = {}; -function increaseCounter(name: string, amount: number) { - if (!counters[name]) { - counters[name] = 0; - } - counters[name] += amount; -} -function flushCounterToMaster() { - if (Object.keys(counters).length === 0) { - return; - } - process.send!(counters); - counters = {}; -} - -async function distributeBalance(source: IKeyringPair, api: ApiPromise, totalAmount: bigint, stages: number) { - let accounts = [source]; - // we don't need source in output array - const failedAccounts = [0]; - - const finalUserAmount = 2 ** stages - 1; - accounts.push(...await findUnusedAddresses(api, finalUserAmount)); - // findUnusedAddresses produces at least 1 request per user - increaseCounter('requests', finalUserAmount); - - for (let stage = 0; stage < stages; stage++) { - let usersWithBalance = 2 ** stage; - let amount = totalAmount / (2n ** BigInt(stage)) - FEE * BigInt(stage); - // console.log(`Stage ${stage}/${stages}, ${usersWithBalance} => ${usersWithBalance * 2} = ${amount}`); - let txs = []; - for (let i = 0; i < usersWithBalance; i++) { - let newUser = accounts[i + usersWithBalance]; - // console.log(`${accounts[i].address} => ${newUser.address} = ${amountToSplit}`); - const tx = api.tx.balances.transfer(newUser.address, amount); - txs.push(submitTransactionAsync(accounts[i], tx).catch(e => { - failedAccounts.push(i + usersWithBalance); - increaseCounter('txFailed', 1); - })); - increaseCounter('tx', 1); - } - await Promise.all(txs); - } - - for (let account of failedAccounts.reverse()) { - accounts.splice(account, 1); - } - return accounts; -} - -if (cluster.isMaster) { - let testDone = false; - usingApi(async (api) => { - let prevCounters: { [key: string]: number } = {}; - while (!testDone) { - for (let name in counters) { - if (!(name in prevCounters)) { - prevCounters[name] = 0; - } - if(counters[name] === prevCounters[name]) { - continue; - } - console.log(`${name.padEnd(15)} = ${counters[name] - prevCounters[name]}`); - prevCounters[name] = counters[name]; - } - await waitNewBlocks(api, 1); - } - }); - let waiting: Promise[] = []; - console.log(`Starting ${os.cpus().length} workers`); - usingApi(async (api) => { - const alice = privateKey('//Alice'); - for (let id in os.cpus()) { - const WORKER_NAME = `//LoadWorker${id}_${Date.now()}`; - const workerAccount = privateKey(WORKER_NAME); - const tx = api.tx.balances.transfer(workerAccount.address, 400n * 10n ** 23n); - await submitTransactionAsync(alice, tx); - - let worker = cluster.fork({ - WORKER_NAME, - STAGES: id + 2 - }); - worker.on('message', msg => { - for (let key in msg) { - increaseCounter(key, msg[key]); - } - }); - waiting.push(new Promise(res => worker.on('exit', res))); - } - await Promise.all(waiting); - testDone = true; - }) -} else { - increaseCounter('startedWorkers', 1); - usingApi(async (api) => { - await distributeBalance(privateKey(process.env.WORKER_NAME as string), api, 400n * 10n ** 22n, 10); - }); - const interval = setInterval(() => { - flushCounterToMaster(); - }, 100); - interval.unref(); -} \ No newline at end of file --- /dev/null +++ b/tests/src/transfer.nload.ts @@ -0,0 +1,113 @@ +import { ApiPromise } from "@polkadot/api"; +import { IKeyringPair } from '@polkadot/types/types'; +import privateKey from "./substrate/privateKey"; +import usingApi, { submitTransactionAsync } from "./substrate/substrate-api"; +import waitNewBlocks from "./substrate/wait-new-blocks"; +import { findUnusedAddresses } from "./util/helpers"; +import * as cluster from 'cluster'; +import os from 'os'; + +// Innacurate transfer fee +const FEE = 10n ** 8n; + +let counters: { [key: string]: number } = {}; +function increaseCounter(name: string, amount: number) { + if (!counters[name]) { + counters[name] = 0; + } + counters[name] += amount; +} +function flushCounterToMaster() { + if (Object.keys(counters).length === 0) { + return; + } + process.send!(counters); + counters = {}; +} + +async function distributeBalance(source: IKeyringPair, api: ApiPromise, totalAmount: bigint, stages: number) { + let accounts = [source]; + // we don't need source in output array + const failedAccounts = [0]; + + const finalUserAmount = 2 ** stages - 1; + accounts.push(...await findUnusedAddresses(api, finalUserAmount)); + // findUnusedAddresses produces at least 1 request per user + increaseCounter('requests', finalUserAmount); + + for (let stage = 0; stage < stages; stage++) { + let usersWithBalance = 2 ** stage; + let amount = totalAmount / (2n ** BigInt(stage)) - FEE * BigInt(stage); + // console.log(`Stage ${stage}/${stages}, ${usersWithBalance} => ${usersWithBalance * 2} = ${amount}`); + let txs = []; + for (let i = 0; i < usersWithBalance; i++) { + let newUser = accounts[i + usersWithBalance]; + // console.log(`${accounts[i].address} => ${newUser.address} = ${amountToSplit}`); + const tx = api.tx.balances.transfer(newUser.address, amount); + txs.push(submitTransactionAsync(accounts[i], tx).catch(e => { + failedAccounts.push(i + usersWithBalance); + increaseCounter('txFailed', 1); + })); + increaseCounter('tx', 1); + } + await Promise.all(txs); + } + + for (let account of failedAccounts.reverse()) { + accounts.splice(account, 1); + } + return accounts; +} + +if (cluster.isMaster) { + let testDone = false; + usingApi(async (api) => { + let prevCounters: { [key: string]: number } = {}; + while (!testDone) { + for (let name in counters) { + if (!(name in prevCounters)) { + prevCounters[name] = 0; + } + if(counters[name] === prevCounters[name]) { + continue; + } + console.log(`${name.padEnd(15)} = ${counters[name] - prevCounters[name]}`); + prevCounters[name] = counters[name]; + } + await waitNewBlocks(api, 1); + } + }); + let waiting: Promise[] = []; + console.log(`Starting ${os.cpus().length} workers`); + usingApi(async (api) => { + const alice = privateKey('//Alice'); + for (let id in os.cpus()) { + const WORKER_NAME = `//LoadWorker${id}_${Date.now()}`; + const workerAccount = privateKey(WORKER_NAME); + const tx = api.tx.balances.transfer(workerAccount.address, 400n * 10n ** 23n); + await submitTransactionAsync(alice, tx); + + let worker = cluster.fork({ + WORKER_NAME, + STAGES: id + 2 + }); + worker.on('message', msg => { + for (let key in msg) { + increaseCounter(key, msg[key]); + } + }); + waiting.push(new Promise(res => worker.on('exit', res))); + } + await Promise.all(waiting); + testDone = true; + }) +} else { + increaseCounter('startedWorkers', 1); + usingApi(async (api) => { + await distributeBalance(privateKey(process.env.WORKER_NAME as string), api, 400n * 10n ** 22n, 10); + }); + const interval = setInterval(() => { + flushCounterToMaster(); + }, 100); + interval.unref(); +} \ No newline at end of file -- gitstuff