Skip to content

Commit cd480fc

Browse files
authored
feat(configuration-generator): add helper to generate networks for e2e and functional tests (#959)
* accept custom timeouts * add helper to generate network configs for e2e / functional tests * style: resolve style guide violations * add to codecov.yml * split script * style: resolve style guide violations
1 parent 57e5e8f commit cd480fc

4 files changed

Lines changed: 229 additions & 1 deletion

File tree

codecov.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ ignore:
22
- "contracts/test"
33
- "packages/contracts"
44
- "packages/utils/benchmark"
5+
- "packages/configuration-generator/bin"
56

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
import envPaths from "env-paths";
2+
import path from "path";
3+
import { Identifiers as AppIdentifiers } from "@mainsail/contracts";
4+
import { makeApplication } from "../distribution/application-factory.js";
5+
import { Identifiers } from "../distribution/identifiers.js";
6+
import { fileURLToPath } from "url";
7+
import { copyFileSync } from "fs";
8+
import { readJSONSync, writeJSONSync } from "fs-extra/esm";
9+
10+
const configurations = [
11+
//
12+
// Functional Tests
13+
// tests/functional/transaction-pool-api/paths/config/
14+
{
15+
network: "devnet",
16+
symbol: "TѦ",
17+
token: "ARK",
18+
distribute: true,
19+
premine: "125000000000000000000000000",
20+
chainId: 10000,
21+
validators: 53,
22+
initialHeight: 0,
23+
overwriteConfig: true,
24+
timeouts: {
25+
blockPrepareTime: 100,
26+
blockTime: 100,
27+
stageTimeout: 100,
28+
stageTimeoutIncrease: 100,
29+
tolerance: 100,
30+
},
31+
postGenerate: (location) => {
32+
// Functional tests run on single node
33+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
34+
35+
for (const file of ["crypto.json", "validators.json", "genesis-wallet.json"]) {
36+
const source = path.join(location, file);
37+
const target = path.join(
38+
__dirname,
39+
"..",
40+
"..",
41+
"..",
42+
"tests",
43+
"functional",
44+
"transaction-pool-api",
45+
"paths",
46+
"config",
47+
file,
48+
);
49+
copyFileSync(source, target);
50+
}
51+
},
52+
},
53+
54+
// E2E Consensus
55+
// tests/e2e/consensus
56+
{
57+
network: "devnet",
58+
symbol: "TѦ",
59+
token: "ARK",
60+
distribute: true,
61+
premine: "125000000000000000000000000",
62+
chainId: 10000,
63+
validators: 5,
64+
initialHeight: 0,
65+
overwriteConfig: true,
66+
timeouts: {
67+
blockPrepareTime: 500,
68+
blockTime: 500,
69+
stageTimeout: 500,
70+
stageTimeoutIncrease: 500,
71+
tolerance: 100,
72+
},
73+
postGenerate: (location) => {
74+
// E2E tests run multiple nodes (1 validator per node)
75+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
76+
77+
// E2E Clients
78+
for (const file of ["crypto.json", "validators.json"]) {
79+
const source = path.join(location, file);
80+
const target = path.join(
81+
__dirname,
82+
"..",
83+
"..",
84+
"..",
85+
"tests",
86+
"e2e",
87+
"clients",
88+
"config",
89+
"core",
90+
file,
91+
);
92+
copyFileSync(source, target);
93+
}
94+
95+
// E2E Consensus
96+
97+
// Validator Node0 - Node4
98+
for (let i = 0; i < 5; i++) {
99+
const validators = readJSONSync(path.join(location, "validators.json"));
100+
validators.secrets = [validators.secrets[i]];
101+
102+
const targetPath = path.join(
103+
__dirname,
104+
"..",
105+
"..",
106+
"..",
107+
"tests",
108+
"e2e",
109+
"consensus",
110+
"nodes",
111+
`node${i}`,
112+
"core",
113+
);
114+
writeJSONSync(path.join(targetPath, "validators.json"), validators, {
115+
spaces: 4,
116+
});
117+
118+
copyFileSync(path.join(location, "crypto.json"), path.join(targetPath, "crypto.json"));
119+
}
120+
121+
// Api Node
122+
for (const file of ["crypto.json"]) {
123+
const source = path.join(location, file);
124+
const target = path.join(
125+
__dirname,
126+
"..",
127+
"..",
128+
"..",
129+
"tests",
130+
"e2e",
131+
"consensus",
132+
"nodes",
133+
`api-node`,
134+
"core",
135+
file,
136+
);
137+
copyFileSync(source, target);
138+
}
139+
},
140+
},
141+
142+
// E2E Snapshot
143+
// tests/e2e/snapshot
144+
{
145+
network: "devnet",
146+
symbol: "TѦ",
147+
token: "ARK",
148+
distribute: true,
149+
premine: "125000000000000000000000000",
150+
chainId: 10000,
151+
initialHeight: 0,
152+
validators: 5,
153+
overwriteConfig: true,
154+
mockFakeValidatorBlsKeys: true,
155+
timeouts: {
156+
blockPrepareTime: 500,
157+
blockTime: 500,
158+
stageTimeout: 500,
159+
stageTimeoutIncrease: 500,
160+
tolerance: 100,
161+
},
162+
snapshot: {
163+
// reuse existing snapshot to build new genesis block
164+
// also see commit: 718b4cf2f1b49df9b80e6474be06fa97acc80d44
165+
path: "../../tests/e2e/snapshot/nodes/node0/core/snapshot/f11b12e6d3a7524482deaacf745d5411d476ae39beeb7ce5141bfeee912cd08d.compressed",
166+
},
167+
postGenerate: (location) => {
168+
// E2E tests run multiple nodes (1 validator per node)
169+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
170+
171+
// Validator Node0 - Node4 (only needs updated crypto.json)
172+
for (let i = 0; i < 5; i++) {
173+
const source = path.join(location, "crypto.json");
174+
const target = path.join(
175+
__dirname,
176+
"..",
177+
"..",
178+
"..",
179+
"tests",
180+
"e2e",
181+
"snapshot",
182+
"nodes",
183+
`node${i}`,
184+
"core",
185+
"crypto.json",
186+
);
187+
copyFileSync(source, target);
188+
}
189+
},
190+
},
191+
];
192+
193+
async function run() {
194+
const paths = envPaths("mainsail", { suffix: "" });
195+
const configCore = path.join(paths.config, "core");
196+
console.log(paths, configCore);
197+
198+
for (const configuration of configurations) {
199+
await generateConfiguration(configCore, configuration);
200+
}
201+
}
202+
203+
const generateConfiguration = async (path, configuration) => {
204+
const app = await makeApplication(path, {});
205+
const generator = app.get(Identifiers.ConfigurationGenerator);
206+
207+
await generator.generate(configuration);
208+
209+
if (configuration.postGenerate) {
210+
configuration.postGenerate(generator.configurationPath);
211+
}
212+
213+
for (const tag of ["evm", "validator", "transaction-pool", "rpc"]) {
214+
if (app.isBoundTagged(AppIdentifiers.Evm.Instance, "instance", tag)) {
215+
await app.getTagged(AppIdentifiers.Evm.Instance, "instance", tag).dispose();
216+
}
217+
}
218+
};
219+
220+
run();

packages/configuration-generator/source/generators/milestones.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class MilestonesGenerator {
2929
decimals: 18,
3030
denomination: 1e18,
3131
},
32-
timeouts: {
32+
timeouts: options.timeouts ?? {
3333
blockPrepareTime: options.blockTime / 2,
3434
blockTime: options.blockTime,
3535
stageTimeout: 2000,

packages/contracts/source/contracts/network-generator.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ export type MilestoneOptions = {
1515
maxBlockGasLimit: number;
1616
maxTxPerBlock: number;
1717
blockTime: number;
18+
timeouts?: {
19+
blockPrepareTime: number;
20+
blockTime: number;
21+
stageTimeout: number;
22+
stageTimeoutIncrease: number;
23+
tolerance: number;
24+
};
1825
epoch: Date;
1926
vendorFieldLength: number;
2027
};

0 commit comments

Comments
 (0)