Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit e6d8c14

Browse files
Stress Tests 1 - QA Tests (#6595)
* 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>
1 parent 3bda14d commit e6d8c14

23 files changed

+942
-186
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ yarn add web3
7777
## Package.json Scripts
7878

7979
| Script | Description |
80-
| ---------------- | ------------------------------------------------------------------ |
80+
| ---------------- |--------------------------------------------------------------------|
8181
| clean | Uses `rimraf` to remove `dist/` |
8282
| build | Uses `tsc` to build all packages |
8383
| lint | Uses `eslint` to lint all packages |
@@ -86,6 +86,7 @@ yarn add web3
8686
| test | Uses `jest` to run unit tests in each package |
8787
| test:integration | Uses `jest` to run tests under `/test/integration` in each package |
8888
| test:unit | Uses `jest` to run tests under `/test/unit` in each package |
89+
| test:manual:long-connection-ws | Runs manual tests for keeping a long WebSocket connection |
8990
| test:manual | Runs manual tests under `test/manual` in the web3 package |
9091

9192
[npm-url]: https://npmjs.org/package/web3

package.json

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
"geth-binary:start": "WEB3_SYSTEM_TEST_BACKEND=geth && ./scripts/geth_binary.sh start",
5454
"geth-binary:start:background": "WEB3_SYSTEM_TEST_BACKEND=geth && ./scripts/geth_binary.sh start 1",
5555
"geth-binary:stop": "WEB3_SYSTEM_TEST_BACKEND=geth && ./scripts/geth_binary.sh stop",
56+
"geth-manual:start:background": "WEB3_SYSTEM_TEST_BACKEND=geth && ./scripts/geth_binary.sh manualStart 1",
57+
"geth-manual:stop": "WEB3_SYSTEM_TEST_BACKEND=geth && ./scripts/geth_binary.sh stop",
5658
"lint": "lerna run lint --stream --parallel",
5759
"lint:fix": "lerna run lint:fix --stream --parallel",
5860
"format": "lerna run format --stream --parallel && prettier --write ./scripts/**/*.ts",
@@ -61,6 +63,7 @@
6163
"test:coverage:integration": "lerna run test:coverage:integration --stream --parallel",
6264
"test:unit": "lerna run test:unit --stream --parallel && jest --config=./scripts/jest.config.js",
6365
"test:integration": "lerna run test:integration --stream",
66+
"test:integration:stress": "lerna run test:integration:stress --stream",
6467
"test:e2e:ganache:http": "./scripts/test-runner.sh ganache http",
6568
"test:e2e:ganache:ws": "./scripts/test-runner.sh ganache ws",
6669
"test:e2e:geth:http": "./scripts/test-runner.sh geth http",
@@ -74,6 +77,10 @@
7477
"test:e2e:mainnet:ws": "./scripts/test-runner.sh mainnet ws",
7578
"test:e2e:sepolia:http": "./scripts/test-runner.sh sepolia http",
7679
"test:e2e:sepolia:ws": "./scripts/test-runner.sh sepolia ws",
80+
"test:stress:geth:ws": "./scripts/test-runner.sh geth-manual ws node manual",
81+
"test:stress:geth:ipc": "./scripts/test-runner.sh geth-manual ipc node manual",
82+
"test:stress:geth:http": "./scripts/test-runner.sh geth-manual http node manual",
83+
"test:e2e:stress:geth:ws:chrome": "./scripts/test-runner.sh geth-manual ws chrome manual",
7784
"generate:accounts": "node ./scripts/gen_accounts.js",
7885
"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\"",
7986
"post-blackbox": "./scripts/verdaccio.sh stop",
@@ -85,11 +92,8 @@
8592
"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",
8693
"test:blackbox:infura:http": "yarn pre-blackbox && ./scripts/verdaccio.sh startBackgroundAndPublish && lerna run test:blackbox:infura:http --stream && yarn post-blackbox",
8794
"test:blackbox:infura:ws": "yarn pre-blackbox && ./scripts/verdaccio.sh startBackgroundAndPublish && lerna run test:blackbox:infura:ws --stream && yarn post-blackbox",
88-
"test:manual:stress:data": "packages/web3/test/stress/start.sh",
89-
"test:manual:stress:validation": "npx ts-node packages/web3/test/stress/validator.ts",
90-
"test:manual:stress": "yarn test:manual:stress:data && yarn test:manual:stress:validation",
91-
"test:manual:long-connection-ws":"node ./packages/web3/test/manual/long_ws_tests/nodejs_test/long_connection_ws.js",
92-
"test:manual":"yarn test:manual:stress && yarn test:manual:long-connection-ws",
95+
"test:manual:long-connection-ws": "node packages/web3/test/stress/long_ws_tests/nodejs_test/long_connection_ws.js",
96+
"test:stress":"yarn test:stress:geth:ws && yarn test:stress:geth:http && yarn test:stress:geth:ipc && yarn test:e2e:stress:geth:ws:chrome",
9397
"husky:install": "husky install",
9498
"husky:uninstall": "husky uninstall",
9599
"postinstall": "yarn build",

packages/web3/.eslintignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ lib
33
hardhat.config.js
44
jest.config.js
55
webpack.config.js
6+
cypress
7+
cypress.config.js
68
.eslintrc.js
7-
webpack.analyze.js
9+
webpack.analyze.js

packages/web3/cypress

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../templates/cypress

packages/web3/cypress.config.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
This file is part of web3.js.
3+
4+
web3.js is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU Lesser General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
web3.js is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public License
15+
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
const config = {
18+
screenshotOnRunFailure: false,
19+
video: false,
20+
e2e: {
21+
// We've imported your old cypress plugins here.
22+
// You may want to clean this up later by importing these.
23+
setupNodeEvents(on, config) {
24+
return require('./cypress/plugins/index.js')(on, config);
25+
},
26+
specPattern: 'test/e2e_manual/**/**/*.test.ts',
27+
excludeSpecPattern: [],
28+
},
29+
};
30+
31+
module.exports = config;

packages/web3/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@
5353
"test:watch": "npm test -- --watch",
5454
"test:unit": "jest --config=./test/unit/jest.config.js",
5555
"test:integration": "jest --config=./test/integration/jest.config.js --forceExit",
56+
"test:integration:stress": "jest --config=./test/stress/jest.config.js --forceExit",
5657
"test:blackbox:ganache:http": "./scripts/black_box_test.sh ganache http",
5758
"test:blackbox:ganache:ws": "./scripts/black_box_test.sh ganache ws",
5859
"test:blackbox:geth:http": "./scripts/black_box_test.sh geth http",
5960
"test:blackbox:geth:ws": "./scripts/black_box_test.sh geth ws",
6061
"test:blackbox:infura:http": "./scripts/black_box_test.sh infura http",
61-
"test:blackbox:infura:ws": "./scripts/black_box_test.sh infura ws"
62+
"test:blackbox:infura:ws": "./scripts/black_box_test.sh infura ws",
63+
"test:e2e:chrome:stress": "npx cypress run --headless --browser chrome"
6264
},
6365
"devDependencies": {
6466
"@truffle/hdwallet-provider": "^2.0.12",

packages/web3/test/stress/index.ts renamed to packages/web3/test/e2e_manual/data.test.ts

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.
1717

1818
/* eslint-disable */
1919
import { Web3 } from 'web3';
20-
import { IpcProvider } from 'web3-providers-ipc';
21-
import accounts from '../shared_fixtures/accounts.json';
22-
import { BasicAbi, BasicBytecode } from '../shared_fixtures/build/Basic';
2320
import WebSocketProvider from 'web3-providers-ws';
21+
import accounts from '../../../../scripts/accounts.json';
22+
import { isWs, isIpc, getSystemTestProvider } from '../../../../scripts/system_tests_utils';
23+
import { BasicAbi, BasicBytecode } from '../../../../fixtures/build/Basic';
24+
2425
const DATA_AMOUNT = 50 * 1024; // 50 kB
2526

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

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

4444
await contract.methods.getStringValue().call();
4545
};
4646

47-
const test = async () => {
48-
const providerString = String(process.env.WEB3_SYSTEM_TEST_PROVIDER);
49-
console.log(`Start test with provider: ${providerString}`);
50-
const provider = providerString.includes('ipc')
51-
? new IpcProvider(providerString)
52-
: providerString;
53-
const web3 = new Web3(provider);
54-
55-
for (const a of accounts) {
56-
const acc = web3.eth.accounts.privateKeyToAccount(a.privateKey);
57-
web3.eth.accounts.wallet.add(acc);
58-
}
47+
describe('huge data', () => {
48+
let web3: Web3;
49+
beforeAll(() => {
50+
web3 = new Web3(getSystemTestProvider());
51+
});
52+
afterAll(() => {
53+
if (isWs || isIpc) {
54+
(web3.provider as unknown as WebSocketProvider).disconnect();
55+
}
56+
});
5957

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

68-
test().catch(console.error);
64+
const prs = [];
65+
for (let i = 0; i < 15; i++) {
66+
prs.push(sendAndGetData(web3, i));
67+
}
68+
await Promise.all(prs);
69+
});
70+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use strict';
2+
3+
const base = require('../config/jest.config');
4+
5+
module.exports = {
6+
...base,
7+
setupFilesAfterEnv: ['<rootDir>/test/e2e/setup.js'],
8+
testMatch: [`<rootDir>/test/e2e_manual/**/*.(spec|test).(js|ts)`],
9+
/**
10+
* restoreMocks [boolean]
11+
*
12+
* Default: false
13+
*
14+
* Automatically restore mock state between every test.
15+
* Equivalent to calling jest.restoreAllMocks() between each test.
16+
* This will lead to any mocks having their fake implementations removed
17+
* and restores their initial implementation.
18+
*/
19+
restoreMocks: true,
20+
21+
/**
22+
* resetModules [boolean]
23+
*
24+
* Default: false
25+
*
26+
* By default, each test file gets its own independent module registry.
27+
* Enabling resetModules goes a step further and resets the module registry before running each individual test.
28+
* This is useful to isolate modules for every test so that local module state doesn't conflict between tests.
29+
* This can be done programmatically using jest.resetModules().
30+
*/
31+
resetModules: true,
32+
};
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
This file is part of web3.js.
3+
4+
web3.js is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU Lesser General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
web3.js is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public License
15+
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
/* eslint-disable */
19+
import WebSocketProvider from 'web3-providers-ws';
20+
import { Web3Account } from 'web3-eth-accounts';
21+
import { Web3, Contract, Numbers, EventLog } from 'web3';
22+
import { BasicBytecode, BasicAbi } from '../../../../fixtures/build/Basic';
23+
import { isWs, isIpc, getSystemTestProvider } from '../../../../scripts/system_tests_utils';
24+
25+
const contracts: { [key: string]: Contract<typeof BasicAbi> } = {};
26+
27+
const deployContracts = async (web3: Web3, accounts: Web3Account[]) => {
28+
const prs = [];
29+
for (let i = 0; i < accounts.length; i++) {
30+
const account = accounts[i];
31+
const sendOptions = { from: account.address };
32+
const deployOptions = {
33+
data: BasicBytecode,
34+
arguments: [123, ''] as [number, string],
35+
gas: BigInt(9000000000000),
36+
gasLimit: BigInt(9000000000000),
37+
type: BigInt(0),
38+
};
39+
const c = new web3.eth.Contract<typeof BasicAbi>(BasicAbi);
40+
prs.push(
41+
c
42+
.deploy(deployOptions)
43+
.send(sendOptions)
44+
.then((contract: typeof c) => {
45+
contracts[account.address] = contract;
46+
}),
47+
);
48+
}
49+
await Promise.all(prs);
50+
};
51+
52+
const addAccount = async (
53+
web3: Web3,
54+
mainAcc: string,
55+
address: string,
56+
privateKey: string,
57+
nonce: Numbers,
58+
) => {
59+
web3.eth.accounts.wallet.add(privateKey);
60+
return web3.eth.sendTransaction({
61+
from: mainAcc,
62+
to: address,
63+
nonce,
64+
gas: 1500000,
65+
value: '1000000000000000000',
66+
});
67+
};
68+
69+
const prepareAccounts = async (web3: Web3, n = 1000) => {
70+
const prs = [];
71+
const list = await web3.eth.personal.getAccounts();
72+
const mainAcc = list[0];
73+
const accountList: Web3Account[] = [];
74+
const nonce = await web3.eth.getTransactionCount(mainAcc);
75+
for (let i = 0; i < n; i++) {
76+
const acc = web3.eth.accounts.create();
77+
prs.push(addAccount(web3, mainAcc, acc.address, acc.privateKey, Number(nonce) + i));
78+
accountList.push(acc);
79+
}
80+
await Promise.all(prs);
81+
return accountList;
82+
};
83+
84+
const sendData = async (account: Web3Account) => {
85+
const contract = contracts[account.address];
86+
return contract.methods
87+
.firesStringEvent(`String event: ${account.address}`)
88+
.send({ from: account.address });
89+
};
90+
91+
const getData = async (account: Web3Account) => {
92+
const contract = contracts[account.address];
93+
await contract.methods.getStringValue().call();
94+
};
95+
96+
const receivedEvents: { [key: string]: EventLog } = {};
97+
const subscribeContract = (acc: Web3Account) => {
98+
const contract = contracts[acc.address];
99+
const event = contract.events.StringEvent();
100+
101+
event.on('data', res => {
102+
if (res.returnValues.str !== `String event: ${acc.address}`) {
103+
throw new Error('Event is not correct');
104+
}
105+
receivedEvents[acc.address] = res;
106+
});
107+
};
108+
const contractSubscriptions = (accounts: Web3Account[]) => {
109+
for (const acc of accounts) {
110+
subscribeContract(acc);
111+
}
112+
};
113+
114+
describe('huge data', () => {
115+
let web3: Web3;
116+
let parallelCount = 100;
117+
let accounts: Web3Account[] = [];
118+
beforeAll(async () => {
119+
parallelCount = isIpc ? 5 : parallelCount;
120+
web3 = new Web3(getSystemTestProvider());
121+
accounts = await prepareAccounts(web3, parallelCount);
122+
await deployContracts(web3, accounts);
123+
});
124+
afterAll(() => {
125+
if (isWs || isIpc) {
126+
(web3.provider as unknown as WebSocketProvider).disconnect();
127+
}
128+
});
129+
it('send requests', async () => {
130+
const sendPrs = [];
131+
for (let i = 0; i < parallelCount; i++) {
132+
sendPrs.push(sendData(accounts[i]));
133+
}
134+
await Promise.all(sendPrs);
135+
// if socket subscribe to events
136+
if (isIpc || isWs) {
137+
contractSubscriptions(accounts);
138+
}
139+
});
140+
it('get requests', async () => {
141+
const getPrs = [];
142+
for (let i = 0; i < parallelCount; i++) {
143+
getPrs.push(getData(accounts[i]));
144+
}
145+
await Promise.all(getPrs);
146+
});
147+
});
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
This file is part of web3.js.
3+
4+
web3.js is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU Lesser General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
web3.js is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public License
15+
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
// Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules
19+
// eslint-disable-next-line @typescript-eslint/no-require-imports
20+
require('../config/setup');
21+
22+
const jestTimeout = 300000;
23+
24+
jest.setTimeout(jestTimeout);

0 commit comments

Comments
 (0)