Skip to content

Commit

Permalink
test: migrate state-transition unit tests to vitest (#6173)
Browse files Browse the repository at this point in the history
* Move state-transition unit tests to vitest

* Update the package.json and remove the segfault retry

* Update packages/state-transition/test/globalSetup.ts

* Update packages/state-transition/test/globalSetup.ts

* Update the run command

* Fix perf test issue

---------

Co-authored-by: Cayman <[email protected]>
  • Loading branch information
nazarhussain and wemeetagain authored Dec 18, 2023
1 parent 7a0a031 commit e09702d
Show file tree
Hide file tree
Showing 32 changed files with 194 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import {defaultOptions as defaultValidatorOptions} from "@lodestar/validator";
// eslint-disable-next-line import/no-relative-packages
import {rangeSyncTest} from "../../../../state-transition/test/perf/params.js";
import {
beforeValue,
getNetworkCachedState,
getNetworkCachedBlock,
// eslint-disable-next-line import/no-relative-packages
} from "../../../../state-transition/test/utils/index.js";
} from "../../../../state-transition/test/utils/testFileCache.js";
import {
beforeValue,
// eslint-disable-next-line import/no-relative-packages
} from "../../../../state-transition/test/utils/beforeValueMocha.js";
import {BeaconChain} from "../../../src/chain/index.js";
import {ExecutionEngineDisabled} from "../../../src/execution/engine/index.js";
import {Eth1ForBlockProductionDisabled} from "../../../src/eth1/index.js";
Expand Down
6 changes: 0 additions & 6 deletions packages/state-transition/.mocharc.yaml

This file was deleted.

2 changes: 1 addition & 1 deletion packages/state-transition/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"check-types": "tsc",
"lint": "eslint --color --ext .ts src/ test/",
"lint:fix": "yarn run lint --fix",
"test:unit": "mocha 'test/unit/**/*.test.ts'",
"test:unit": "vitest --run --dir test/unit/ --coverage",
"check-readme": "typescript-docs-verifier"
},
"types": "lib/index.d.ts",
Expand Down
2 changes: 2 additions & 0 deletions packages/state-transition/test/globalSetup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export async function setup(): Promise<void> {}
export async function teardown(): Promise<void> {}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
CachedBeaconStateAltair,
beforeProcessEpoch,
} from "../../../src/index.js";
import {getNetworkCachedState, beforeValue, LazyValue} from "../../utils/index.js";
import {beforeValue, LazyValue} from "../../utils/beforeValueMocha.js";
import {getNetworkCachedState} from "../../utils/testFileCache.js";
import {StateEpoch} from "../types.js";
import {altairState} from "../params.js";
import {processJustificationAndFinalization} from "../../../src/epoch/processJustificationAndFinalization.js";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
CachedBeaconStateAltair,
beforeProcessEpoch,
} from "../../../src/index.js";
import {getNetworkCachedState, beforeValue, LazyValue} from "../../utils/index.js";
import {beforeValue, LazyValue} from "../../utils/beforeValueMocha.js";
import {getNetworkCachedState} from "../../utils/testFileCache.js";
import {StateEpoch} from "../types.js";
import {capellaState} from "../params.js";
import {processJustificationAndFinalization} from "../../../src/epoch/processJustificationAndFinalization.js";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
CachedBeaconStatePhase0,
beforeProcessEpoch,
} from "../../../src/index.js";
import {getNetworkCachedState, beforeValue, LazyValue} from "../../utils/index.js";
import {beforeValue, LazyValue} from "../../utils/beforeValueMocha.js";
import {getNetworkCachedState} from "../../utils/testFileCache.js";
import {StateEpoch} from "../types.js";
import {phase0State} from "../params.js";
import {processEpoch} from "../../../src/epoch/index.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {expect} from "chai";
import {describe, it, expect} from "vitest";
import {config} from "@lodestar/config/default";
import {FAR_FUTURE_EPOCH, MAX_EFFECTIVE_BALANCE} from "@lodestar/params";
import {phase0, ssz} from "@lodestar/types";
Expand Down Expand Up @@ -35,18 +35,16 @@ describe("validate indexed attestation", () => {
},
];

for (const testValue of testValues) {
it(testValue.name, function () {
const attestationData = ssz.phase0.AttestationData.defaultValue();
attestationData.source.epoch = 0;
attestationData.target.epoch = 1;
it.each(testValues)("$name", ({indices, expectedValue}) => {
const attestationData = ssz.phase0.AttestationData.defaultValue();
attestationData.source.epoch = 0;
attestationData.target.epoch = 1;

const indexedAttestation: phase0.IndexedAttestation = {
attestingIndices: testValue.indices,
data: attestationData,
signature: EMPTY_SIGNATURE,
};
expect(isValidIndexedAttestation(state, indexedAttestation, false)).to.be.equal(testValue.expectedValue);
});
}
const indexedAttestation: phase0.IndexedAttestation = {
attestingIndices: indices,
data: attestationData,
signature: EMPTY_SIGNATURE,
};
expect(isValidIndexedAttestation(state, indexedAttestation, false)).toBe(expectedValue);
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {expect} from "chai";
import {describe, it, expect} from "vitest";
import {getExpectedWithdrawals} from "../../../src/block/processWithdrawals.js";
import {numValidators} from "../../perf/util.js";
import {getExpectedWithdrawalsTestData, WithdrawalOpts} from "../../utils/capella.js";
Expand Down Expand Up @@ -38,8 +38,8 @@ describe("getExpectedWithdrawals", () => {

it(`getExpectedWithdrawals ${vc} ${caseID}`, () => {
const {sampledValidators, withdrawals} = getExpectedWithdrawals(state.value);
expect(sampledValidators).equals(opts.sampled, "Wrong sampledValidators");
expect(withdrawals.length).equals(opts.withdrawals, "Wrong withdrawals");
expect(sampledValidators).toBe(opts.sampled);
expect(withdrawals.length).toBe(opts.withdrawals);
});
}
});
32 changes: 10 additions & 22 deletions packages/state-transition/test/unit/cachedBeaconState.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {expect} from "chai";
import {describe, it, expect} from "vitest";
import {ssz} from "@lodestar/types";
import {toHexString} from "@lodestar/utils";
import {config} from "@lodestar/config/default";
Expand All @@ -16,18 +16,15 @@ describe("CachedBeaconState", () => {
const state2 = state1.clone();

state1.slot = 1;
expect(state2.slot).to.equal(0, "state2.slot was mutated");
expect(state2.slot).toBe(0);

const prevRoot = state2.currentJustifiedCheckpoint.root;
const newRoot = Buffer.alloc(32, 1);
state1.currentJustifiedCheckpoint.root = newRoot;
expect(toHexString(state2.currentJustifiedCheckpoint.root)).to.equal(
toHexString(prevRoot),
"state2.currentJustifiedCheckpoint.root was mutated"
);
expect(toHexString(state2.currentJustifiedCheckpoint.root)).toBe(toHexString(prevRoot));

state1.epochCtx.epoch = 1;
expect(state2.epochCtx.epoch).to.equal(0, "state2.epochCtx.epoch was mutated");
expect(state2.epochCtx.epoch).toBe(0);
});

it("Auto-commit on hashTreeRoot", () => {
Expand All @@ -40,10 +37,7 @@ describe("CachedBeaconState", () => {

// Only commit state1 beforehand
cp1.commit();
expect(toHexString(cp1.hashTreeRoot())).to.equal(
toHexString(cp2.hashTreeRoot()),
".hashTreeRoot() does not automatically commit"
);
expect(toHexString(cp1.hashTreeRoot())).toBe(toHexString(cp2.hashTreeRoot()));
});

it("Auto-commit on serialize", () => {
Expand All @@ -55,10 +49,7 @@ describe("CachedBeaconState", () => {

// Only commit state1 beforehand
cp1.commit();
expect(toHexString(cp1.serialize())).to.equal(
toHexString(cp2.serialize()),
".serialize() does not automatically commit"
);
expect(toHexString(cp1.serialize())).toBe(toHexString(cp2.serialize()));
});

describe("loadCachedBeaconState", () => {
Expand Down Expand Up @@ -138,16 +129,13 @@ describe("CachedBeaconState", () => {
const stateBytes = state.serialize();
const newCachedState = loadUnfinalizedCachedBeaconState(seedState, stateBytes, {skipSyncCommitteeCache: true});
const newStateBytes = newCachedState.serialize();
expect(newStateBytes).to.be.deep.equal(stateBytes, "loadState: state bytes are not equal");
expect(newCachedState.hashTreeRoot()).to.be.deep.equal(
state.hashTreeRoot(),
"loadState: state root is not equal"
);
expect(newStateBytes).toEqual(stateBytes);
expect(newCachedState.hashTreeRoot()).toEqual(state.hashTreeRoot());

// confirm loadUnfinalizedCachedBeaconState() result
for (let i = 0; i < newCachedState.validators.length; i++) {
expect(newCachedState.epochCtx.pubkey2index.get(newCachedState.validators.get(i).pubkey)).to.be.equal(i);
expect(newCachedState.epochCtx.index2pubkey[i].toBytes()).to.be.deep.equal(pubkeys[i]);
expect(newCachedState.epochCtx.pubkey2index.get(newCachedState.validators.get(i).pubkey)).toBe(i);
expect(newCachedState.epochCtx.index2pubkey[i].toBytes()).toEqual(pubkeys[i]);
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions packages/state-transition/test/unit/constants.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {expect} from "chai";
import {describe, it, expect} from "vitest";
import * as blst from "@chainsafe/blst";
import {G2_POINT_AT_INFINITY} from "../../src/index.js";

describe("constants", () => {
it("G2_POINT_AT_INFINITY", () => {
const p2 = blst.Signature.fromBytes(G2_POINT_AT_INFINITY);
expect(p2.value.is_inf()).to.equal(true, "is not infinity");
expect(p2.value.is_inf()).toBe(true);
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import crypto from "node:crypto";
import {expect} from "chai";
import {describe, it, expect} from "vitest";
import bls from "@chainsafe/bls";
import {BitArray} from "@chainsafe/ssz";
import {config} from "@lodestar/config/default";
Expand Down Expand Up @@ -67,7 +67,7 @@ describe("signatureSets", () => {
const state = generateCachedState(config, {validators});

const signatureSets = getBlockSignatureSets(state, signedBlock);
expect(signatureSets.length).to.equal(
expect(signatureSets.length).toBe(
// block signature
1 +
// randao reveal
Expand Down
4 changes: 2 additions & 2 deletions packages/state-transition/test/unit/upgradeState.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {expect} from "chai";
import {expect, describe, it} from "vitest";
import {ssz} from "@lodestar/types";
import {ForkName} from "@lodestar/params";
import {createBeaconConfig, ChainForkConfig, createChainForkConfig} from "@lodestar/config";
Expand All @@ -22,7 +22,7 @@ describe("upgradeState", () => {
{skipSyncCommitteeCache: true}
);
const newState = upgradeStateToDeneb(stateView);
expect(() => newState.toValue()).to.not.throw();
expect(() => newState.toValue()).not.toThrow();
});
});

Expand Down
19 changes: 10 additions & 9 deletions packages/state-transition/test/unit/util/aggregator.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {expect} from "chai";
import {describe, it, expect, beforeAll} from "vitest";
import {fromHexString} from "@chainsafe/ssz";
import {
SYNC_COMMITTEE_SIZE,
Expand All @@ -13,10 +13,10 @@ import {isAggregatorFromCommitteeLength, isSyncCommitteeAggregator} from "../../
describe("isAttestationAggregator", function () {
const committeeLength = 130;

before("Ensure constants don't change", () => {
beforeAll(() => {
expect({
TARGET_AGGREGATORS_PER_COMMITTEE,
}).to.deep.equal({
}).toEqual({
TARGET_AGGREGATORS_PER_COMMITTEE: 16,
});
});
Expand All @@ -28,26 +28,27 @@ describe("isAttestationAggregator", function () {
"0x8191d16330837620f0ed85d0d3d52af5b56f7cec12658fa391814251d4b32977eb2e6ca055367354fd63175f8d1d2d7b0678c3c482b738f96a0df40bd06450d99c301a659b8396c227ed781abb37a1604297922219374772ab36b46b84817036"
)
);
expect(result).to.be.equal(false);
expect(result).toBe(false);
});

it("should be true", function () {
const result = isAggregatorFromCommitteeLength(
committeeLength,
fromHexString(
"0xa8f8bb92931234ca6d8a34530526bcd6a4cfa3bf33bd0470200dc8fa3ebdc3ba24bc8c6e994d58a0f884eb24336d746c01a29693ed0354c0862c2d5de5859e3f58747045182844d267ba232058f7df1867a406f63a1eb8afec0cf3f00a115125"
)
);
expect(result).to.be.equal(true);
expect(result).toBe(true);
});
});

describe("isSyncCommitteeAggregator", function () {
before("Ensure constants don't change", () => {
beforeAll(() => {
expect({
SYNC_COMMITTEE_SIZE,
SYNC_COMMITTEE_SUBNET_COUNT,
TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE,
}).to.deep.equal({
}).toEqual({
SYNC_COMMITTEE_SIZE: 512,
SYNC_COMMITTEE_SUBNET_COUNT: 4,
TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE: 16,
Expand All @@ -60,7 +61,7 @@ describe("isSyncCommitteeAggregator", function () {
"0x8191d16330837620f0ed85d0d3d52af5b56f7cec12658fa391814251d4b32977eb2e6ca055367354fd63175f8d1d2d7b0678c3c482b738f96a0df40bd06450d99c301a659b8396c227ed781abb37a1604297922219374772ab36b46b84817036"
)
);
expect(result).to.be.equal(false);
expect(result).toBe(false);
});

// NOTE: Invalid sig, bruteforced last characters to get a true result
Expand All @@ -70,6 +71,6 @@ describe("isSyncCommitteeAggregator", function () {
"0xa8f8bb92931234ca6d8a34530526bcd6a4cfa3bf33bd0470200dc8fa3ebdc3ba24bc8c6e994d58a0f884eb24336d746c01a29693ed0354c0862c2d5de5859e3f58747045182844d267ba232058f7df1867a406f63a1eb8afec0cf3f00a115142"
)
);
expect(result).to.be.equal(true);
expect(result).toBe(true);
});
});
21 changes: 9 additions & 12 deletions packages/state-transition/test/unit/util/balance.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {assert, expect} from "chai";
import {describe, it, expect} from "vitest";
import {config as minimalConfig} from "@lodestar/config/default";

import {EFFECTIVE_BALANCE_INCREMENT} from "@lodestar/params";
Expand All @@ -23,7 +23,7 @@ describe("getTotalBalance", () => {

const result = getTotalBalance(state, validatorIndices);
const expected = BigInt(num * validatorBalance);
assert(result === expected, `Expected: ${expected} :: Result: ${result}`);
expect(result).toEqual(expected);
});

it("should return correct balances - 5 validators", () => {
Expand All @@ -34,21 +34,21 @@ describe("getTotalBalance", () => {
const validatorIndices: ValidatorIndex[] = Array.from({length: num}, (_, i) => i);

const result = getTotalBalance(state, validatorIndices);
const expected = EFFECTIVE_BALANCE_INCREMENT;
assert(result === BigInt(expected), `Expected: ${expected} :: Result: ${result}`);
const expected = BigInt(EFFECTIVE_BALANCE_INCREMENT);
expect(result).toEqual(expected);
});
});

describe("increaseBalance", () => {
it("should add to a validators balance", () => {
const state = generateCachedState();
state.balances.push(0);
expect(state.balances.get(0)).to.be.equal(0);
expect(state.balances.get(0)).toBe(0);

const delta = 5;
for (let i = 1; i < 10; i++) {
increaseBalance(state, 0, delta);
expect(state.balances.get(0)).to.be.equal(delta * i);
expect(state.balances.get(0)).toBe(delta * i);
}
});
});
Expand All @@ -62,7 +62,7 @@ describe("decreaseBalance", () => {
const delta = 5;
for (let i = 1; i < 10; i++) {
decreaseBalance(state, 0, delta);
expect(state.balances.get(0)).to.be.equal(initial - delta * i);
expect(state.balances.get(0)).toBe(initial - delta * i);
}
});

Expand All @@ -72,7 +72,7 @@ describe("decreaseBalance", () => {
state.balances.push(initial);
const delta = 11;
decreaseBalance(state, 0, delta);
expect(state.balances.get(0)).to.be.equal(0);
expect(state.balances.get(0)).toBe(0);
});
});

Expand All @@ -99,9 +99,6 @@ describe("getEffectiveBalanceIncrementsZeroInactive", () => {
: 0;
}

expect(getEffectiveBalanceIncrementsZeroInactive(justifiedState)).to.be.deep.equal(
effectiveBalances,
"wrong effectiveBalances"
);
expect(getEffectiveBalanceIncrementsZeroInactive(justifiedState)).toEqual(effectiveBalances);
});
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {describe, it} from "vitest";
import {createBeaconConfig} from "@lodestar/config";
import {config} from "@lodestar/config/default";
import {ssz} from "@lodestar/types";
Expand Down
Loading

0 comments on commit e09702d

Please sign in to comment.