-
Notifications
You must be signed in to change notification settings - Fork 158
feat: add support for scenario testing #660
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
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
f47b513
feat: add account management methods to GRE
tmigone 2c07fda
feat: split e2e tests into config and init
tmigone ed48c72
chore: rework named accounts generation
tmigone 95d944f
feat: replace getAccounts with getTestAccounts
tmigone d3ec33b
feat: add demo scenario and task
tmigone b459fb5
feat: scenario 1 wip
tmigone 05b67cb
fix: use latest GRE
tmigone ef99316
fix: rebase tmigone/gre-accounts2
tmigone a944676
fix: update code to latest GRE
tmigone 4879a74
fix: create subgraphs
tmigone 1e4e888
fix: make scenario1 test pass wip
tmigone 8f89f05
chore: remove incorrect comment
tmigone 5af9650
chore: add scenario testing docs
tmigone 91b467b
feat: add flag to skip running scripts in scenario testing
tmigone File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# Testing | ||
|
||
Testing is done with the following stack: | ||
|
||
- [Waffle](https://getwaffle.io/) | ||
- [Hardhat](https://hardhat.org/) | ||
- [Typescript](https://www.typescriptlang.org/) | ||
- [Ethers](https://docs.ethers.io/v5/) | ||
|
||
## Unit testing | ||
|
||
To test all the smart contracts, use `yarn test`. | ||
To test a single file run: `npx hardhat test test/<FILE_NAME>.ts` | ||
|
||
## E2E Testing | ||
|
||
End to end tests are also available and can be run against a local network or a live network. These can be useful to validate that a protocol deployment is configured and working as expected. | ||
|
||
There are several types of e2e tests which can be run separately: | ||
- **deployment/config** | ||
- Test the configuration of deployed contracts (parameters that don't change over time). | ||
- Can be run against any network at any time and the tests should pass. | ||
- Only read only interactions with the blockchain. | ||
- Example: a test validating the curation default reserve ratio matches the value in the graph config file. | ||
- **deployment/init** | ||
- Test the initialization of deployed contracts (parameters that change with protocol usage). | ||
- Can be run against a "fresh" protocol deployment. Running these tests against a protocol with pre-existing state will probably fail. | ||
- Only read only interactions with the blockchain. | ||
- Example: a test validating that the GRT total supply equals 10B, this is only true on a freshly deployed protocol until the first allocation is closed and protocol issuance kicks in. | ||
- **scenarios** | ||
- Test the execution of common protocol actions. | ||
- Can be run against any network at any time and the tests should pass. | ||
- Read and write interactions with the blockchain. _Requires an account with sufficient balance!_ | ||
- Example: a test validating that a user can add signal to a subgraph. | ||
|
||
### Hardhat local node | ||
|
||
To run all e2e tests against a hardhat local node run: | ||
|
||
```bash | ||
yarn test:e2e | ||
``` | ||
|
||
The command will perform the following actions: | ||
|
||
- Start a hardhat node (localhost) | ||
- Run `migrate:accounts` hardhat task to create keys for all protocol roles (deployer, governor, arbiter, etc). This currently doesn't support multisig accounts. | ||
- Run `migrate` hardhat task to deploy the protocol | ||
- Run `migrate:ownership` hardhat task to transfer ownership of governed contracts to the governor | ||
- Run `migrate:unpause` to unpause the protocol | ||
- Run `e2e` hardhat task to run all e2e tests, including scenarios | ||
|
||
### Other networks | ||
|
||
To run tests against a live testnet or even mainnet run: | ||
|
||
```bash | ||
# All e2e tests | ||
npx hardhat e2e --network <network> --graph-config config/graph.<network>.yml | ||
|
||
# Only deployment config tests | ||
npx hardhat e2e:config --network <network> --graph-config config/graph.<network>.yml | ||
|
||
# Only deployment init tests | ||
npx hardhat e2e:init --network <network> --graph-config config/graph.<network>.yml | ||
|
||
# Only a specific scenario | ||
npx hardhat e2e:scenario <scenario> --network <network> --graph-config config/graph.<network>.yml | ||
``` | ||
|
||
Note that this command will only run the tests so you need to be sure the protocol is already deployed and the graph config file and address book files are up to date. | ||
|
||
### How to add scenarios | ||
|
||
Scenarios are defined by an optional script and a test file: | ||
|
||
- Optional ts script | ||
- The objective of this script is to perform actions on the protocol to advance it's state to the desired one. | ||
- Should follow hardhat script convention. | ||
- Should be named e2e/scenarios/{scenario-name}.ts. | ||
- They run before the test file. | ||
- Test file | ||
- Should be named e2e/scenarios/{scenario-name}.test.ts. | ||
- Standard chai/mocha/hardhat/ethers test file. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { BigNumberish, Signer } from 'ethers' | ||
import { NetworkContracts } from '../../../cli/contracts' | ||
|
||
export const signal = async ( | ||
contracts: NetworkContracts, | ||
curator: Signer, | ||
subgraphId: string, | ||
amount: BigNumberish, | ||
): Promise<void> => { | ||
const { GNS } = contracts | ||
|
||
// Add signal | ||
const tx = await GNS.connect(curator).mintSignal(subgraphId, amount, 0) | ||
await tx.wait() | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,18 @@ | ||
import hre from 'hardhat' | ||
import { Staking } from '../../../build/types/Staking' | ||
import { BigNumberish, Signer } from 'ethers' | ||
import { NetworkContracts } from '../../../cli/contracts' | ||
|
||
export const stake = async (amountWei: string): Promise<void> => { | ||
const graph = hre.graph() | ||
export const stake = async ( | ||
contracts: NetworkContracts, | ||
indexer: Signer, | ||
amount: BigNumberish, | ||
): Promise<void> => { | ||
const { GraphToken, Staking } = contracts | ||
|
||
// Approve | ||
const stakeAmountWei = hre.ethers.utils.parseEther(amountWei).toString() | ||
await graph.contracts.GraphToken.approve(graph.contracts.Staking.address, stakeAmountWei) | ||
const txApprove = await GraphToken.connect(indexer).approve(Staking.address, amount) | ||
tmigone marked this conversation as resolved.
Show resolved
Hide resolved
|
||
await txApprove.wait() | ||
|
||
// Stake | ||
await graph.contracts.Staking.stake(stakeAmountWei) | ||
const txStake = await Staking.connect(indexer).stake(amount) | ||
await txStake.wait() | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { Signer, utils } from 'ethers' | ||
import { NetworkContracts } from '../../../cli/contracts' | ||
|
||
const { hexlify, randomBytes } = utils | ||
|
||
export const publishNewSubgraph = async ( | ||
contracts: NetworkContracts, | ||
publisher: Signer, | ||
deploymentId: string, | ||
): Promise<void> => { | ||
const tx = await contracts.GNS.connect(publisher).publishNewSubgraph( | ||
deploymentId, | ||
hexlify(randomBytes(32)), | ||
tmigone marked this conversation as resolved.
Show resolved
Hide resolved
|
||
hexlify(randomBytes(32)), | ||
) | ||
await tx.wait() | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { BigNumberish, ContractReceipt, Signer } from 'ethers' | ||
import { NetworkContracts } from '../../../cli/contracts' | ||
|
||
export const airdrop = async ( | ||
contracts: NetworkContracts, | ||
sender: Signer, | ||
beneficiaries: string[], | ||
amount: BigNumberish, | ||
): Promise<void> => { | ||
const { GraphToken } = contracts | ||
|
||
const txs: Promise<ContractReceipt>[] = [] | ||
|
||
for (const beneficiary of beneficiaries) { | ||
tmigone marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const tx = await GraphToken.connect(sender).transfer(beneficiary, amount) | ||
txs.push(tx.wait()) | ||
} | ||
await Promise.all(txs) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' | ||
import { expect } from 'chai' | ||
import { solidityKeccak256 } from 'ethers/lib/utils' | ||
import hre from 'hardhat' | ||
import { fixture } from './scenario1' | ||
|
||
describe('Scenario 1', () => { | ||
const { | ||
contracts: { GraphToken, Staking, GNS }, | ||
getTestAccounts, | ||
} = hre.graph() | ||
|
||
let indexer1: SignerWithAddress | ||
let indexer2: SignerWithAddress | ||
let curator1: SignerWithAddress | ||
let curator2: SignerWithAddress | ||
let curator3: SignerWithAddress | ||
let subgraphOwner: SignerWithAddress | ||
|
||
let indexers: SignerWithAddress[] = [] | ||
let curators: SignerWithAddress[] = [] | ||
|
||
before(async () => { | ||
;[indexer1, indexer2, subgraphOwner, curator1, curator2, curator3] = await getTestAccounts() | ||
indexers = [indexer1, indexer2] | ||
curators = [curator1, curator2, curator3] | ||
}) | ||
|
||
describe('GRT balances', () => { | ||
it('indexer1 should match airdropped amount minus staked', async function () { | ||
const balance = await GraphToken.balanceOf(indexer1.address) | ||
expect(balance).eq(fixture.grtAmount.sub(fixture.indexer1.stake)) | ||
}) | ||
|
||
it('indexer2 should match airdropped amount minus staked', async function () { | ||
const balance = await GraphToken.balanceOf(indexer2.address) | ||
expect(balance).eq(fixture.grtAmount.sub(fixture.indexer2.stake)) | ||
}) | ||
|
||
it('curator should match airdropped amount', async function () { | ||
for (const account of curators) { | ||
const balance = await GraphToken.balanceOf(account.address) | ||
expect(balance).eq(fixture.grtAmount) | ||
} | ||
}) | ||
}) | ||
|
||
describe('Staking', () => { | ||
it('indexer1 should have tokens staked', async function () { | ||
const tokensStaked = (await Staking.stakes(indexer1.address)).tokensStaked | ||
expect(tokensStaked).eq(fixture.indexer1.stake) | ||
}) | ||
it('indexer2 should have tokens staked', async function () { | ||
const tokensStaked = (await Staking.stakes(indexer2.address)).tokensStaked | ||
expect(tokensStaked).eq(fixture.indexer2.stake) | ||
}) | ||
}) | ||
|
||
// describe('Subgraphs', () => { | ||
// for (const subgraphDeploymentId of fixture.subgraphs) { | ||
// it(`${subgraphDeploymentId} is published`, async function () { | ||
// const seqID = await GNS.nextAccountSeqID(subgraphOwner.address) | ||
// const subgraphId = solidityKeccak256(['address', 'uint256'], [subgraphOwner.address, seqID]) | ||
|
||
// await GNS.subgraphs(subgraphDeploymentId) | ||
|
||
// const isPublished = await GNS.isPublished(subgraphId) | ||
// expect(isPublished).eq(true) | ||
// }) | ||
// } | ||
// }) | ||
}) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.