Skip to content

Commit

Permalink
Stress Tests 1 - QA Tests (#6595)
Browse files Browse the repository at this point in the history
* add data stress test

* fix unit tests

* fix

* try to fix validator test

* fix ipc tests

* fix load test

* fix

* move to tests folder

* moved

* fix

* add send tests

* browser tests

* move validator test to web3 package

* fix

* fix naming

* add browser test

* fix

* move to TS. remove time logs

* fix start.sh

* fix validation test run script

* fix name

* move to TS

* move to jest

* add browser tests

* fix

* fixes

* fix

* fix tests count

---------

Co-authored-by: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
  • Loading branch information
avkos and Muhammad-Altabba committed Nov 28, 2023
1 parent 3bda14d commit e6d8c14
Show file tree
Hide file tree
Showing 23 changed files with 942 additions and 186 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ yarn add web3
## Package.json Scripts

| Script | Description |
| ---------------- | ------------------------------------------------------------------ |
| ---------------- |--------------------------------------------------------------------|
| clean | Uses `rimraf` to remove `dist/` |
| build | Uses `tsc` to build all packages |
| lint | Uses `eslint` to lint all packages |
Expand All @@ -86,6 +86,7 @@ yarn add web3
| test | Uses `jest` to run unit tests in each package |
| test:integration | Uses `jest` to run tests under `/test/integration` in each package |
| test:unit | Uses `jest` to run tests under `/test/unit` in each package |
| test:manual:long-connection-ws | Runs manual tests for keeping a long WebSocket connection |
| test:manual | Runs manual tests under `test/manual` in the web3 package |

[npm-url]: https://npmjs.org/package/web3
Expand Down
14 changes: 9 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
"geth-binary:start": "WEB3_SYSTEM_TEST_BACKEND=geth && ./scripts/geth_binary.sh start",
"geth-binary:start:background": "WEB3_SYSTEM_TEST_BACKEND=geth && ./scripts/geth_binary.sh start 1",
"geth-binary:stop": "WEB3_SYSTEM_TEST_BACKEND=geth && ./scripts/geth_binary.sh stop",
"geth-manual:start:background": "WEB3_SYSTEM_TEST_BACKEND=geth && ./scripts/geth_binary.sh manualStart 1",
"geth-manual:stop": "WEB3_SYSTEM_TEST_BACKEND=geth && ./scripts/geth_binary.sh stop",
"lint": "lerna run lint --stream --parallel",
"lint:fix": "lerna run lint:fix --stream --parallel",
"format": "lerna run format --stream --parallel && prettier --write ./scripts/**/*.ts",
Expand All @@ -61,6 +63,7 @@
"test:coverage:integration": "lerna run test:coverage:integration --stream --parallel",
"test:unit": "lerna run test:unit --stream --parallel && jest --config=./scripts/jest.config.js",
"test:integration": "lerna run test:integration --stream",
"test:integration:stress": "lerna run test:integration:stress --stream",
"test:e2e:ganache:http": "./scripts/test-runner.sh ganache http",
"test:e2e:ganache:ws": "./scripts/test-runner.sh ganache ws",
"test:e2e:geth:http": "./scripts/test-runner.sh geth http",
Expand All @@ -74,6 +77,10 @@
"test:e2e:mainnet:ws": "./scripts/test-runner.sh mainnet ws",
"test:e2e:sepolia:http": "./scripts/test-runner.sh sepolia http",
"test:e2e:sepolia:ws": "./scripts/test-runner.sh sepolia ws",
"test:stress:geth:ws": "./scripts/test-runner.sh geth-manual ws node manual",
"test:stress:geth:ipc": "./scripts/test-runner.sh geth-manual ipc node manual",
"test:stress:geth:http": "./scripts/test-runner.sh geth-manual http node manual",
"test:e2e:stress:geth:ws:chrome": "./scripts/test-runner.sh geth-manual ws chrome manual",
"generate:accounts": "node ./scripts/gen_accounts.js",
"pre-blackbox": "yarn config set registry http://localhost:4873 && git init && git config --global user.email \"ci@github.com\" && git config --global user.name \"CI\"",
"post-blackbox": "./scripts/verdaccio.sh stop",
Expand All @@ -85,11 +92,8 @@
"test:blackbox:geth:ws": "yarn pre-blackbox && yarn geth:start:background && ./scripts/verdaccio.sh startBackgroundAndPublish && lerna run test:blackbox:geth:ws --stream && yarn post-blackbox:geth",
"test:blackbox:infura:http": "yarn pre-blackbox && ./scripts/verdaccio.sh startBackgroundAndPublish && lerna run test:blackbox:infura:http --stream && yarn post-blackbox",
"test:blackbox:infura:ws": "yarn pre-blackbox && ./scripts/verdaccio.sh startBackgroundAndPublish && lerna run test:blackbox:infura:ws --stream && yarn post-blackbox",
"test:manual:stress:data": "packages/web3/test/stress/start.sh",
"test:manual:stress:validation": "npx ts-node packages/web3/test/stress/validator.ts",
"test:manual:stress": "yarn test:manual:stress:data && yarn test:manual:stress:validation",
"test:manual:long-connection-ws":"node ./packages/web3/test/manual/long_ws_tests/nodejs_test/long_connection_ws.js",
"test:manual":"yarn test:manual:stress && yarn test:manual:long-connection-ws",
"test:manual:long-connection-ws": "node packages/web3/test/stress/long_ws_tests/nodejs_test/long_connection_ws.js",
"test:stress":"yarn test:stress:geth:ws && yarn test:stress:geth:http && yarn test:stress:geth:ipc && yarn test:e2e:stress:geth:ws:chrome",
"husky:install": "husky install",
"husky:uninstall": "husky uninstall",
"postinstall": "yarn build",
Expand Down
4 changes: 3 additions & 1 deletion packages/web3/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ lib
hardhat.config.js
jest.config.js
webpack.config.js
cypress
cypress.config.js
.eslintrc.js
webpack.analyze.js
webpack.analyze.js
1 change: 1 addition & 0 deletions packages/web3/cypress
31 changes: 31 additions & 0 deletions packages/web3/cypress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/
const config = {
screenshotOnRunFailure: false,
video: false,
e2e: {
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents(on, config) {
return require('./cypress/plugins/index.js')(on, config);
},
specPattern: 'test/e2e_manual/**/**/*.test.ts',
excludeSpecPattern: [],
},
};

module.exports = config;
4 changes: 3 additions & 1 deletion packages/web3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,14 @@
"test:watch": "npm test -- --watch",
"test:unit": "jest --config=./test/unit/jest.config.js",
"test:integration": "jest --config=./test/integration/jest.config.js --forceExit",
"test:integration:stress": "jest --config=./test/stress/jest.config.js --forceExit",
"test:blackbox:ganache:http": "./scripts/black_box_test.sh ganache http",
"test:blackbox:ganache:ws": "./scripts/black_box_test.sh ganache ws",
"test:blackbox:geth:http": "./scripts/black_box_test.sh geth http",
"test:blackbox:geth:ws": "./scripts/black_box_test.sh geth ws",
"test:blackbox:infura:http": "./scripts/black_box_test.sh infura http",
"test:blackbox:infura:ws": "./scripts/black_box_test.sh infura ws"
"test:blackbox:infura:ws": "./scripts/black_box_test.sh infura ws",
"test:e2e:chrome:stress": "npx cypress run --headless --browser chrome"
},
"devDependencies": {
"@truffle/hdwallet-provider": "^2.0.12",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.

/* eslint-disable */
import { Web3 } from 'web3';
import { IpcProvider } from 'web3-providers-ipc';
import accounts from '../shared_fixtures/accounts.json';
import { BasicAbi, BasicBytecode } from '../shared_fixtures/build/Basic';
import WebSocketProvider from 'web3-providers-ws';
import accounts from '../../../../scripts/accounts.json';
import { isWs, isIpc, getSystemTestProvider } from '../../../../scripts/system_tests_utils';
import { BasicAbi, BasicBytecode } from '../../../../fixtures/build/Basic';

const DATA_AMOUNT = 50 * 1024; // 50 kB

const sendAndGetData = async (web3: Web3, i: number) => {
Expand All @@ -37,32 +38,33 @@ const sendAndGetData = async (web3: Web3, i: number) => {
const contract = await c.deploy(deployOptions).send(sendOptions);

await contract.methods
// @ts-ignore
.setValues(1, 'A'.repeat(DATA_AMOUNT), true)
.send({ from: accounts[i].address });

await contract.methods.getStringValue().call();
};

const test = async () => {
const providerString = String(process.env.WEB3_SYSTEM_TEST_PROVIDER);
console.log(`Start test with provider: ${providerString}`);
const provider = providerString.includes('ipc')
? new IpcProvider(providerString)
: providerString;
const web3 = new Web3(provider);

for (const a of accounts) {
const acc = web3.eth.accounts.privateKeyToAccount(a.privateKey);
web3.eth.accounts.wallet.add(acc);
}
describe('huge data', () => {
let web3: Web3;
beforeAll(() => {
web3 = new Web3(getSystemTestProvider());
});
afterAll(() => {
if (isWs || isIpc) {
(web3.provider as unknown as WebSocketProvider).disconnect();
}
});

const prs = [];
for (let i = 0; i < 15; i++) {
prs.push(sendAndGetData(web3, i));
}
await Promise.all(prs);
(web3.provider as unknown as WebSocketProvider).disconnect();
};
it('send and get', async () => {
for (const a of accounts) {
const acc = web3.eth.accounts.privateKeyToAccount(a.privateKey);
web3.eth.accounts.wallet.add(acc);
}

test().catch(console.error);
const prs = [];
for (let i = 0; i < 15; i++) {
prs.push(sendAndGetData(web3, i));
}
await Promise.all(prs);
});
});
32 changes: 32 additions & 0 deletions packages/web3/test/e2e_manual/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

const base = require('../config/jest.config');

module.exports = {
...base,
setupFilesAfterEnv: ['<rootDir>/test/e2e/setup.js'],
testMatch: [`<rootDir>/test/e2e_manual/**/*.(spec|test).(js|ts)`],
/**
* restoreMocks [boolean]
*
* Default: false
*
* Automatically restore mock state between every test.
* Equivalent to calling jest.restoreAllMocks() between each test.
* This will lead to any mocks having their fake implementations removed
* and restores their initial implementation.
*/
restoreMocks: true,

/**
* resetModules [boolean]
*
* Default: false
*
* By default, each test file gets its own independent module registry.
* Enabling resetModules goes a step further and resets the module registry before running each individual test.
* This is useful to isolate modules for every test so that local module state doesn't conflict between tests.
* This can be done programmatically using jest.resetModules().
*/
resetModules: true,
};
147 changes: 147 additions & 0 deletions packages/web3/test/e2e_manual/requests.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/

/* eslint-disable */
import WebSocketProvider from 'web3-providers-ws';
import { Web3Account } from 'web3-eth-accounts';
import { Web3, Contract, Numbers, EventLog } from 'web3';
import { BasicBytecode, BasicAbi } from '../../../../fixtures/build/Basic';
import { isWs, isIpc, getSystemTestProvider } from '../../../../scripts/system_tests_utils';

const contracts: { [key: string]: Contract<typeof BasicAbi> } = {};

const deployContracts = async (web3: Web3, accounts: Web3Account[]) => {
const prs = [];
for (let i = 0; i < accounts.length; i++) {
const account = accounts[i];
const sendOptions = { from: account.address };
const deployOptions = {
data: BasicBytecode,
arguments: [123, ''] as [number, string],
gas: BigInt(9000000000000),
gasLimit: BigInt(9000000000000),
type: BigInt(0),
};
const c = new web3.eth.Contract<typeof BasicAbi>(BasicAbi);
prs.push(
c
.deploy(deployOptions)
.send(sendOptions)
.then((contract: typeof c) => {
contracts[account.address] = contract;
}),
);
}
await Promise.all(prs);
};

const addAccount = async (
web3: Web3,
mainAcc: string,
address: string,
privateKey: string,
nonce: Numbers,
) => {
web3.eth.accounts.wallet.add(privateKey);
return web3.eth.sendTransaction({
from: mainAcc,
to: address,
nonce,
gas: 1500000,
value: '1000000000000000000',
});
};

const prepareAccounts = async (web3: Web3, n = 1000) => {
const prs = [];
const list = await web3.eth.personal.getAccounts();
const mainAcc = list[0];
const accountList: Web3Account[] = [];
const nonce = await web3.eth.getTransactionCount(mainAcc);
for (let i = 0; i < n; i++) {
const acc = web3.eth.accounts.create();
prs.push(addAccount(web3, mainAcc, acc.address, acc.privateKey, Number(nonce) + i));
accountList.push(acc);
}
await Promise.all(prs);
return accountList;
};

const sendData = async (account: Web3Account) => {
const contract = contracts[account.address];
return contract.methods
.firesStringEvent(`String event: ${account.address}`)
.send({ from: account.address });
};

const getData = async (account: Web3Account) => {
const contract = contracts[account.address];
await contract.methods.getStringValue().call();
};

const receivedEvents: { [key: string]: EventLog } = {};
const subscribeContract = (acc: Web3Account) => {
const contract = contracts[acc.address];
const event = contract.events.StringEvent();

event.on('data', res => {
if (res.returnValues.str !== `String event: ${acc.address}`) {
throw new Error('Event is not correct');
}
receivedEvents[acc.address] = res;
});
};
const contractSubscriptions = (accounts: Web3Account[]) => {
for (const acc of accounts) {
subscribeContract(acc);
}
};

describe('huge data', () => {
let web3: Web3;
let parallelCount = 100;
let accounts: Web3Account[] = [];
beforeAll(async () => {
parallelCount = isIpc ? 5 : parallelCount;
web3 = new Web3(getSystemTestProvider());
accounts = await prepareAccounts(web3, parallelCount);
await deployContracts(web3, accounts);
});
afterAll(() => {
if (isWs || isIpc) {
(web3.provider as unknown as WebSocketProvider).disconnect();
}
});
it('send requests', async () => {
const sendPrs = [];
for (let i = 0; i < parallelCount; i++) {
sendPrs.push(sendData(accounts[i]));
}
await Promise.all(sendPrs);
// if socket subscribe to events
if (isIpc || isWs) {
contractSubscriptions(accounts);
}
});
it('get requests', async () => {
const getPrs = [];
for (let i = 0; i < parallelCount; i++) {
getPrs.push(getData(accounts[i]));
}
await Promise.all(getPrs);
});
});
24 changes: 24 additions & 0 deletions packages/web3/test/e2e_manual/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/

// Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules
// eslint-disable-next-line @typescript-eslint/no-require-imports
require('../config/setup');

const jestTimeout = 300000;

jest.setTimeout(jestTimeout);
Loading

0 comments on commit e6d8c14

Please sign in to comment.