Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(prover): improve test coverage #5648

Merged
merged 41 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
5d8fa2a
Create a package structure
nazarhussain Jun 14, 2023
b2ec5b3
Add utilities to test-util package
nazarhussain Jun 14, 2023
06a6a75
Add e2e test for prover cli
nazarhussain Jun 14, 2023
d7154b1
Make the status code optional
nazarhussain Jun 14, 2023
83f3231
Fix the e2e test
nazarhussain Jun 14, 2023
7689a9f
Add preset support to prover
nazarhussain Jun 26, 2023
0abce24
Update the e2e tests for the cli package
nazarhussain Jun 26, 2023
dd98af5
Fix utility methods
nazarhussain Jun 26, 2023
070f731
Use the child process logic in sim tests
nazarhussain Jun 26, 2023
0416160
Fix child process runner
nazarhussain Jun 26, 2023
eabb009
Add logPrefix to identify job
nazarhussain Jun 26, 2023
dc853b8
Fix health timeout check
nazarhussain Jun 26, 2023
890bee2
Increase the health timeout
nazarhussain Jun 26, 2023
ce7c249
Add a check on healthy process
nazarhussain Jun 26, 2023
fb3733d
Fix docker network create
nazarhussain Jun 26, 2023
50488ba
Update the test code for the mocha context
nazarhussain Jun 27, 2023
8fbe438
Fix the e2e abort case
nazarhussain Jun 29, 2023
a5080c4
Update the test-util package to fix yarn warning
nazarhussain Jun 29, 2023
f28f20c
Fix lint error
nazarhussain Jun 29, 2023
90d470d
Update the doc comments
nazarhussain Jun 29, 2023
d7bb3e0
Merge branch 'unstable' into nh/5647-prover-tests
nazarhussain Jul 3, 2023
67384d9
Update code as per feedback
nazarhussain Jul 3, 2023
bac66f8
Reuse expectKeys function
nazarhussain Jul 3, 2023
22dbf0e
Sort the packages order
nazarhussain Jul 3, 2023
cc557ba
Fix lint error
nazarhussain Jul 3, 2023
ce433f5
Fix lint erorr for project dependency
nazarhussain Jul 3, 2023
55e34e8
Fix the code change for e2e tests
nazarhussain Jul 3, 2023
e2f333b
Revert "Fix the code change for e2e tests"
nazarhussain Jul 3, 2023
7ad4843
Revert the expectKeys
nazarhussain Jul 3, 2023
242117f
Upgrade package dependency
nazarhussain Jul 3, 2023
e2544dd
Rename the package @lodestar/test-util to @lodestar/test-utils
nazarhussain Jul 3, 2023
94d52f2
Update import references
nazarhussain Jul 3, 2023
b7d37bb
Update import references
nazarhussain Jul 3, 2023
23164bf
Update import references
nazarhussain Jul 3, 2023
ec44489
Start the proxy with dev network
nazarhussain Jul 4, 2023
c3d35e5
Add wait time for the proxy server
nazarhussain Jul 4, 2023
a991553
Fix the e2e test args
nazarhussain Jul 4, 2023
40e7980
Write the preset overrides to file
nazarhussain Jul 4, 2023
e3d079b
Make directory for params file
nazarhussain Jul 5, 2023
6294fd7
Fix custom network params options for prover cli
nazarhussain Jul 7, 2023
4d12604
Update command to use node loader
nazarhussain Jul 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"@types/got": "^9.6.12",
"@types/inquirer": "^9.0.3",
"@types/lodash": "^4.14.192",
"@types/yargs": "^17.0.24"
"@types/yargs": "^17.0.24",
"@lodestar/test-utils": "^1.9.1"
}
}
45 changes: 25 additions & 20 deletions packages/cli/test/e2e/blsToExecutionchange.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,41 @@ import {ApiError, getClient} from "@lodestar/api";
import {config} from "@lodestar/config/default";
import {interopSecretKey} from "@lodestar/state-transition";
import {toHexString} from "@chainsafe/ssz";
import {execCliCommand, spawnCliCommand, stopChildProcess} from "@lodestar/test-utils";
import {testFilesDir} from "../utils.js";
import {describeCliTest, execCli} from "../utils/childprocRunner.js";
import {itDone} from "../utils/runUtils.js";

describeCliTest("bLSToExecutionChange cmd", function ({spawnCli}) {
describe("bLSToExecutionChange cmd", function () {
this.timeout("60s");

itDone("Perform bLSToExecutionChange", async function (done) {
it("Perform bLSToExecutionChange", async () => {
const restPort = 9596;

const devBnProc = spawnCli({pipeStdToParent: false, logPrefix: "dev"}, [
// ⏎
"dev",
`--dataDir=${path.join(testFilesDir, "dev-bls-to-execution-change")}`,
"--genesisValidators=8",
"--startValidators=0..7",
"--rest",
`--rest.port=${restPort}`,
// Speed up test to make genesis happen faster
"--params.SECONDS_PER_SLOT=2",
]);
const devBnProc = await spawnCliCommand(
"packages/cli/bin/lodestar.js",
[
"dev",
`--dataDir=${path.join(testFilesDir, "dev-bls-to-execution-change")}`,
"--genesisValidators=8",
"--startValidators=0..7",
"--rest",
`--rest.port=${restPort}`,
// Speed up test to make genesis happen faster
"--params.SECONDS_PER_SLOT=2",
],
{pipeStdioToParent: false, logPrefix: "dev"}
);

// Exit early if process exits
devBnProc.on("exit", (code) => {
if (code !== null && code > 0) {
done(Error(`devBnProc process exited with code ${code}`));
throw new Error(`devBnProc process exited with code ${code}`);
}
});

const baseUrl = `http://127.0.0.1:${restPort}`;
const client = getClient({baseUrl}, {config});
// To cleanup the event stream connection
const httpClientController = new AbortController();
const client = getClient({baseUrl, getAbortSignal: () => httpClientController.signal}, {config});

// Wait for beacon node API to be available + genesis
await retry(
Expand All @@ -57,8 +62,7 @@ describeCliTest("bLSToExecutionChange cmd", function ({spawnCli}) {
// 2 0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4
// 3 0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653

await execCli([
// ⏎
await execCliCommand("packages/cli/bin/lodestar.js", [
"validator",
"bls-to-execution-change",
"--network=dev",
Expand All @@ -80,8 +84,9 @@ describeCliTest("bLSToExecutionChange cmd", function ({spawnCli}) {
throw Error("Invalid message generated");
}

httpClientController.abort();
devBnProc.kill("SIGINT");
await sleep(1000);
devBnProc.kill("SIGKILL");
await stopChildProcess(devBnProc, "SIGKILL");
});
});
38 changes: 21 additions & 17 deletions packages/cli/test/e2e/importFromFsDirect.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import fs from "node:fs";
import path from "node:path";
import {rimraf} from "rimraf";
import {getMochaContext} from "@lodestar/test-utils/mocha";
import {testFilesDir} from "../utils.js";
import {describeCliTest} from "../utils/childprocRunner.js";
import {getAfterEachCallbacks} from "../utils/runUtils.js";
import {cachedPubkeysHex, cachedSeckeysHex} from "../utils/cachedKeys.js";
import {expectKeys, getKeymanagerTestRunner} from "../utils/keymanagerTestRunners.js";
import {expectKeys, startValidatorWithKeyManager} from "../utils/validator.js";
import {getKeystoresStr} from "../utils/keystores.js";

describeCliTest("import from fs same cmd as validate", function ({spawnCli}) {
describe("import from fs same cmd as validate", function () {
const testContext = getMochaContext(this);
this.timeout("30s");

const dataDir = path.join(testFilesDir, "import-and-validate-test");
const importFromDir = path.join(dataDir, "eth2.0_deposit_out");
const passphraseFilepath = path.join(importFromDir, "password.text");
Expand All @@ -18,9 +20,6 @@ describeCliTest("import from fs same cmd as validate", function ({spawnCli}) {
rimraf.sync(importFromDir);
});

const afterEachCallbacks = getAfterEachCallbacks();
const itKeymanagerStep = getKeymanagerTestRunner({args: {spawnCli}, afterEachCallbacks, dataDir});

const passphrase = "AAAAAAAA0000000000";
const keyCount = 2;
const pubkeys = cachedPubkeysHex.slice(0, keyCount);
Expand All @@ -38,18 +37,23 @@ describeCliTest("import from fs same cmd as validate", function ({spawnCli}) {
});

// Check that there are not keys loaded without adding extra args `--importKeystores`
itKeymanagerStep("run 'validator' check keys are loaded", async function (keymanagerClient) {
it("run 'validator' there are no keys loaded", async () => {
const {keymanagerClient} = await startValidatorWithKeyManager([], {
dataDir,
logPrefix: "case-1",
testContext,
});

await expectKeys(keymanagerClient, [], "Wrong listKeys response data");
});

// Run validator with extra arguments to load keystores in same step
itKeymanagerStep(
"run 'validator' check keys are loaded",
async function (keymanagerClient) {
await expectKeys(keymanagerClient, pubkeys, "Wrong listKeys response data");
},
{
validatorCmdExtraArgs: [`--importKeystores=${importFromDir}`, `--importKeystoresPassword=${passphraseFilepath}`],
}
);
it("run 'validator' check keys are loaded", async () => {
const {keymanagerClient} = await startValidatorWithKeyManager(
[`--importKeystores=${importFromDir}`, `--importKeystoresPassword=${passphraseFilepath}`],
{dataDir, logPrefix: "case-2", testContext}
);

await expectKeys(keymanagerClient, pubkeys, "Wrong listKeys response data");
});
});
27 changes: 12 additions & 15 deletions packages/cli/test/e2e/importFromFsPreStep.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import fs from "node:fs";
import path from "node:path";
import {rimraf} from "rimraf";
import {expect} from "chai";
import {getMochaContext} from "@lodestar/test-utils/mocha";
import {execCliCommand} from "@lodestar/test-utils";
import {testFilesDir} from "../utils.js";
import {describeCliTest, execCli} from "../utils/childprocRunner.js";
import {getAfterEachCallbacks} from "../utils/runUtils.js";
import {cachedPubkeysHex, cachedSeckeysHex} from "../utils/cachedKeys.js";
import {expectKeys, getKeymanagerTestRunner} from "../utils/keymanagerTestRunners.js";
import {expectKeys, startValidatorWithKeyManager} from "../utils/validator.js";
import {getKeystoresStr} from "../utils/keystores.js";

describeCliTest("import from fs then validate", function ({spawnCli}) {
describe("import from fs then validate", function () {
const testContext = getMochaContext(this);
this.timeout("30s");

const dataDir = path.join(testFilesDir, "import-then-validate-test");
const importFromDir = path.join(dataDir, "eth2.0_deposit_out");
const passphraseFilepath = path.join(importFromDir, "password.text");
Expand All @@ -19,9 +22,6 @@ describeCliTest("import from fs then validate", function ({spawnCli}) {
rimraf.sync(importFromDir);
});

const afterEachCallbacks = getAfterEachCallbacks();
const itKeymanagerStep = getKeymanagerTestRunner({args: {spawnCli}, afterEachCallbacks, dataDir});

const passphrase = "AAAAAAAA0000000000";
const keyCount = 2;
const pubkeys = cachedPubkeysHex.slice(0, keyCount);
Expand All @@ -37,8 +37,7 @@ describeCliTest("import from fs then validate", function ({spawnCli}) {
fs.writeFileSync(path.join(importFromDir, `keystore_${i}.json`), keystoresStr[i]);
}

const stdout = await execCli([
// ⏎
const stdout = await execCliCommand("packages/cli/bin/lodestar.js", [
"validator import",
`--dataDir ${dataDir}`,
`--importKeystores ${importFromDir}`,
Expand All @@ -54,18 +53,16 @@ describeCliTest("import from fs then validate", function ({spawnCli}) {
fs.mkdirSync(path.join(dataDir, "keystores"), {recursive: true});
fs.mkdirSync(path.join(dataDir, "secrets"), {recursive: true});

const stdout = await execCli([
// ⏎
"validator list",
`--dataDir ${dataDir}`,
]);
const stdout = await execCliCommand("packages/cli/bin/lodestar.js", ["validator list", `--dataDir ${dataDir}`]);

for (let i = 0; i < keyCount; i++) {
expect(stdout).includes(pubkeys[i], `stdout should include imported pubkey[${i}]`);
}
});

itKeymanagerStep("run 'validator' check keys are loaded", async function (keymanagerClient) {
it("run 'validator' check keys are loaded", async function () {
const {keymanagerClient} = await startValidatorWithKeyManager([], {dataDir, testContext});

await expectKeys(keymanagerClient, pubkeys, "Wrong listKeys response data");
});
});
43 changes: 24 additions & 19 deletions packages/cli/test/e2e/importKeystoresFromApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,24 @@ import {DeletionStatus, getClient, ImportStatus} from "@lodestar/api/keymanager"
import {config} from "@lodestar/config/default";
import {Interchange} from "@lodestar/validator";
import {ApiError, HttpStatusCode} from "@lodestar/api";
import {bufferStderr, spawnCliCommand} from "@lodestar/test-utils";
import {getMochaContext} from "@lodestar/test-utils/mocha";
import {testFilesDir} from "../utils.js";
import {bufferStderr, describeCliTest} from "../utils/childprocRunner.js";
import {cachedPubkeysHex, cachedSeckeysHex} from "../utils/cachedKeys.js";
import {expectDeepEquals, getAfterEachCallbacks} from "../utils/runUtils.js";
import {expectKeys, getKeymanagerTestRunner} from "../utils/keymanagerTestRunners.js";
import {expectDeepEquals} from "../utils/runUtils.js";
import {expectKeys, startValidatorWithKeyManager} from "../utils/validator.js";
import {getKeystoresStr} from "../utils/keystores.js";

describeCliTest("import keystores from api", function ({spawnCli}) {
describe("import keystores from api", function () {
const testContext = getMochaContext(this);
this.timeout("30s");

const dataDir = path.join(testFilesDir, "import-keystores-test");

before("Clean dataDir", () => {
rimraf.sync(dataDir);
});

const afterEachCallbacks = getAfterEachCallbacks();
const itKeymanagerStep = getKeymanagerTestRunner({args: {spawnCli}, afterEachCallbacks, dataDir});

/** Generated from const sk = bls.SecretKey.fromKeygen(Buffer.alloc(32, 0xaa)); */
const passphrase = "AAAAAAAA0000000000";
const keyCount = 2;
Expand Down Expand Up @@ -55,7 +56,8 @@ describeCliTest("import keystores from api", function ({spawnCli}) {

const slashingProtectionStr = JSON.stringify(slashingProtection);

itKeymanagerStep("run 'validator' and import remote keys from API", async function (keymanagerClient) {
it("run 'validator' and import remote keys from API", async () => {
const {keymanagerClient} = await startValidatorWithKeyManager([], {dataDir, testContext});
// Produce and encrypt keystores
const keystoresStr = await getKeystoresStr(passphrase, secretKeys);

Expand Down Expand Up @@ -84,16 +86,14 @@ describeCliTest("import keystores from api", function ({spawnCli}) {
);

// Attempt to run a second process and expect the keystore lock to throw
const vcProc2 = spawnCli({pipeStdToParent: true, logPrefix: "vc-2"}, [
// ⏎
"validator",
`--dataDir=${dataDir}`,
]);
const validator = await spawnCliCommand("packages/cli/bin/lodestar.js", ["validator", "--dataDir", dataDir], {
logPrefix: "vc-2",
});

await new Promise<void>((resolve, reject) => {
// logger.error is printed to stdout, Yargs errors are printed in stderr
const vcProc2Stderr = bufferStderr(vcProc2);
vcProc2.on("exit", (code) => {
const vcProc2Stderr = bufferStderr(validator);
validator.on("exit", (code) => {
if (code !== null && code > 0) {
// process should exit with code > 0, and an error related to locks. Sample error:
// vc 351591: ✖ Error: EEXIST: file already exists, open '/tmp/tmp-351554-dMctEAj7sJIz/import-keystores-test/keystores/0x8be678633e927aa0435addad5dcd5283fef6110d91362519cd6d43e61f6c017d724fa579cc4b2972134e050b6ba120c0/voting-keystore.json.lock'
Expand All @@ -111,7 +111,9 @@ describeCliTest("import keystores from api", function ({spawnCli}) {
});
});

itKeymanagerStep("run 'validator' check keys are loaded + delete", async function (keymanagerClient) {
it("run 'validator' check keys are loaded + delete", async function () {
const {keymanagerClient} = await startValidatorWithKeyManager([], {dataDir, testContext});

// Check that keys imported in previous it() are still there
await expectKeys(keymanagerClient, pubkeys, "Wrong listKeys before deleting");

Expand All @@ -128,13 +130,16 @@ describeCliTest("import keystores from api", function ({spawnCli}) {
await expectKeys(keymanagerClient, [], "Wrong listKeys after deleting");
});

itKeymanagerStep("different process check no keys are loaded", async function (keymanagerClient) {
it("different process check no keys are loaded", async function () {
const {keymanagerClient} = await startValidatorWithKeyManager([], {dataDir, testContext});
// After deleting there should be no keys
await expectKeys(keymanagerClient, [], "Wrong listKeys");
});

itKeymanagerStep("reject calls without bearerToken", async function (_, {keymanagerUrl}) {
const keymanagerClientNoAuth = getClient({baseUrl: keymanagerUrl, bearerToken: undefined}, {config});
it("reject calls without bearerToken", async function () {
await startValidatorWithKeyManager([], {dataDir, testContext});

const keymanagerClientNoAuth = getClient({baseUrl: "http://localhost:38011", bearerToken: undefined}, {config});
const res = await keymanagerClientNoAuth.listRemoteKeys();
expect(res.ok).to.be.false;
expect(res.error?.code).to.be.eql(HttpStatusCode.UNAUTHORIZED);
Expand Down
48 changes: 27 additions & 21 deletions packages/cli/test/e2e/importRemoteKeysFromApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,40 @@ import {expect} from "chai";
import {Api, DeleteRemoteKeyStatus, getClient, ImportRemoteKeyStatus} from "@lodestar/api/keymanager";
import {config} from "@lodestar/config/default";
import {ApiError, HttpStatusCode} from "@lodestar/api";
import {getMochaContext} from "@lodestar/test-utils/mocha";
import {testFilesDir} from "../utils.js";
import {describeCliTest} from "../utils/childprocRunner.js";
import {cachedPubkeysHex} from "../utils/cachedKeys.js";
import {expectDeepEquals, getAfterEachCallbacks} from "../utils/runUtils.js";
import {getKeymanagerTestRunner} from "../utils/keymanagerTestRunners.js";
import {expectDeepEquals} from "../utils/runUtils.js";
import {startValidatorWithKeyManager} from "../utils/validator.js";

const url = "https://remote.signer";

async function expectKeys(keymanagerClient: Api, expectedPubkeys: string[], message: string): Promise<void> {
nazarhussain marked this conversation as resolved.
Show resolved Hide resolved
const remoteKeys = await keymanagerClient.listRemoteKeys();
ApiError.assert(remoteKeys);
expectDeepEquals(
remoteKeys.response.data,
expectedPubkeys.map((pubkey) => ({pubkey, url, readonly: false})),
message
);
}

describe("import remoteKeys from api", function () {
const testContext = getMochaContext(this);
this.timeout("30s");

describeCliTest("import remoteKeys from api", function ({spawnCli}) {
const dataDir = path.join(testFilesDir, "import-remoteKeys-test");

before("Clean dataDir", () => {
rimraf.sync(dataDir);
});

const afterEachCallbacks = getAfterEachCallbacks();
const itKeymanagerStep = getKeymanagerTestRunner({args: {spawnCli}, afterEachCallbacks, dataDir});

/** Generated from const sk = bls.SecretKey.fromKeygen(Buffer.alloc(32, 0xaa)); */
const url = "https://remote.signer";
const pubkeysToAdd = [cachedPubkeysHex[0], cachedPubkeysHex[1]];

itKeymanagerStep("run 'validator' and import remote keys from API", async function (keymanagerClient) {
it("run 'validator' and import remote keys from API", async () => {
const {keymanagerClient} = await startValidatorWithKeyManager([], {dataDir, testContext});

// Wrap in retry since the API may not be listening yet
await expectKeys(keymanagerClient, [], "Wrong listRemoteKeys before importing");

Expand All @@ -50,7 +63,8 @@ describeCliTest("import remoteKeys from api", function ({spawnCli}) {
);
});

itKeymanagerStep("run 'validator' check keys are loaded + delete", async function (keymanagerClient) {
it("run 'validator' check keys are loaded + delete", async function () {
const {keymanagerClient} = await startValidatorWithKeyManager([], {dataDir, testContext});
// Check that keys imported in previous it() are still there
await expectKeys(keymanagerClient, pubkeysToAdd, "Wrong listRemoteKeys before deleting");

Expand All @@ -67,20 +81,12 @@ describeCliTest("import remoteKeys from api", function ({spawnCli}) {
await expectKeys(keymanagerClient, [], "Wrong listRemoteKeys after deleting");
});

itKeymanagerStep("reject calls without bearerToken", async function (_, {keymanagerUrl}) {
it("reject calls without bearerToken", async function () {
await startValidatorWithKeyManager([], {dataDir, testContext});
const keymanagerUrl = "http://localhost:38011";
const keymanagerClientNoAuth = getClient({baseUrl: keymanagerUrl, bearerToken: undefined}, {config});
const res = await keymanagerClientNoAuth.listRemoteKeys();
expect(res.ok).to.be.false;
expect(res.error?.code).to.be.eql(HttpStatusCode.UNAUTHORIZED);
});

async function expectKeys(keymanagerClient: Api, expectedPubkeys: string[], message: string): Promise<void> {
const remoteKeys = await keymanagerClient.listRemoteKeys();
ApiError.assert(remoteKeys);
expectDeepEquals(
remoteKeys.response.data,
expectedPubkeys.map((pubkey) => ({pubkey, url, readonly: false})),
message
);
}
});
Loading
Loading