git.delta.rocks / unique-network / refs/commits / bab6ffec254b

difftreelog

Merge branch 'develop' into feature/NFTPAR-281_overflow_tests

Yaroslav Bolyukin2021-02-12parents: #7f526e1 #0219ca5.patch.diff
in: master

3 files changed

modifiedtests/package.jsondiffbeforeafterboth
before · tests/package.json
1{2  "name": "NftTests",3  "version": "1.0.0",4  "description": "Substrate Nft tests",5  "main": "",6  "devDependencies": {7    "@polkadot/dev": "^0.61.24",8    "@polkadot/ts": "^0.3.59",9    "@polkadot/typegen": "^3.6.4",10    "@polkadot/util-crypto": "^5.4.4",11    "@types/chai": "^4.2.12",12    "@types/chai-as-promised": "^7.1.3",13    "@types/mocha": "^8.0.3",14    "chai": "^4.2.0",15    "mocha": "^8.1.1",16    "ts-node": "^9.0.0",17    "tslint": "^5.20.1",18    "typescript": "^3.9.7"19  },20  "scripts": {21    "test": "mocha --timeout 9999999 -r ts-node/register ./**/*.test.ts",22    "load": "mocha --timeout 9999999 -r ts-node/register ./**/*.load.ts",23    "testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts",24    "testSetSchemaVersion": "mocha --timeout 9999999 -r ts-node/register ./**/setSchemaVersion.test.ts",25    "testSetVariableMetaData": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetaData.test.ts",26    "testSetCollectionLimits": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionLimits.test.ts",27    "testRemoveCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionAdmin.test.ts",28    "testRemoveFromWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/removeFromWhiteList.test.ts",29    "testConnection": "mocha --timeout 9999999 -r ts-node/register ./**/connection.test.ts",30    "testCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts",31    "testCreateMultipleItems": "mocha --timeout 9999999 -r ts-node/register ./**/createMultipleItems.test.ts",32    "testApprove": "mocha --timeout 9999999 -r ts-node/register ./**/approve.test.ts",33    "testTransferFrom": "mocha --timeout 9999999 -r ts-node/register ./**/transferFrom.test.ts",34    "testCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts",35    "testToggleContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/toggleContractWhiteList.test.ts",36    "testAddToContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/addToContractWhiteList.test.ts",37    "testTransfer": "mocha --timeout 9999999 -r ts-node/register ./**/transfer.test.ts",38    "testBurnItem": "mocha --timeout 9999999 -r ts-node/register ./**/burnItem.test.ts",39    "testSetMintPermission": "mocha --timeout 9999999 -r ts-node/register ./**/setMintPermission.test.ts",40    "testCreditFeesToTreasury": "mocha --timeout 9999999 -r ts-node/register ./**/creditFeesToTreasury.test.ts",41    "testEnableContractSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/enableContractSponsoring.test.ts",42    "testSetContractSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setContractSponsoringRateLimit.test.ts",43    "testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts"44  },45  "author": "",46  "license": "SEE LICENSE IN ../LICENSE",47  "homepage": "",48  "dependencies": {49    "@polkadot/api": "^3.6.4",50    "@polkadot/api-contract": "^3.6.4",51    "@polkadot/util": "^3.6.4",52    "bignumber.js": "^9.0.0",53    "chai-as-promised": "^7.1.1"54  },55  "standard": {56    "globals": [57      "it",58      "assert",59      "beforeEach",60      "afterEach",61      "describe",62      "contract",63      "artifacts"64    ]65  }66}
addedtests/src/transfer.nload.tsdiffbeforeafterboth
--- /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<void>[] = [];
+    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
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -228,11 +228,11 @@
   });
 }
 
-export async function findUnusedAddress(api: ApiPromise): Promise<IKeyringPair> {
+export async function findUnusedAddress(api: ApiPromise, seedAddition = ''): Promise<IKeyringPair> {
   let bal = new BigNumber(0);
   let unused;
   do {
-    const randomSeed = 'seed' +  Math.floor(Math.random() * Math.floor(10000));
+    const randomSeed = 'seed' +  Math.floor(Math.random() * Math.floor(10000)) + seedAddition;
     const keyring = new Keyring({ type: 'sr25519' });
     unused = keyring.addFromUri(`//${randomSeed}`);
     bal = new BigNumber((await api.query.system.account(unused.address)).data.free.toString());