Skip to content

Commit c926251

Browse files
committed
tests: Switch integration tests to mine-on-demand
Instead of mining a block every 2s, mine blocks only on demand, simplifying the setup and making it much nicer to keep anvil state for future runs
1 parent 16c828b commit c926251

File tree

5 files changed

+52
-27
lines changed

5 files changed

+52
-27
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ jobs:
171171
run: pnpm install
172172

173173
- name: Start anvil
174-
run: anvil --gas-limit 100000000000 --base-fee 1 --block-time 2 --timestamp 1743944919 --port 3021 &
174+
run: anvil --gas-limit 100000000000 --base-fee 1 --timestamp 1743944919 --port 3021 &
175175

176176
- name: Build graph-node
177177
run: just build --test integration_tests

flake.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@
197197
timestamp = 1743944919;
198198
gasLimit = 100000000000;
199199
baseFee = 1;
200-
blockTime = 2;
200+
blockTime = null;
201201
state = "./.data/integration/anvil/state.json";
202202
stateInterval = 30;
203203
preserveHistoricalStates = true;

tests/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ services:
2525
image: ghcr.io/foundry-rs/foundry:v1.4.0
2626
ports:
2727
- '3021:8545'
28-
command: "'anvil --host 0.0.0.0 --gas-limit 100000000000 --base-fee 1 --block-time 2 --timestamp 1743944919 --mnemonic \"test test test test test test test test test test test junk\"'"
28+
command: "'anvil --host 0.0.0.0 --gas-limit 100000000000 --base-fee 1 --timestamp 1743944919 --mnemonic \"test test test test test test test test test test test junk\"'"
2929

3030
# graph-node ports:
3131
# json-rpc: 8020

tests/src/contract.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use graph::prelude::{
55
json_abi::JsonAbi,
66
network::{Ethereum, TransactionBuilder},
77
primitives::{Address, Bytes, U256},
8-
providers::{Provider, ProviderBuilder, WalletProvider},
8+
providers::{ext::AnvilApi, Provider, ProviderBuilder, WalletProvider},
99
rpc::types::{Block, TransactionReceipt, TransactionRequest},
1010
signers::local::PrivateKeySigner,
1111
},
@@ -280,4 +280,40 @@ impl Contract {
280280
.ok()
281281
.flatten()
282282
}
283+
284+
/// Mine the specified number of empty blocks using Anvil's evm_mine RPC.
285+
pub async fn mine_blocks(count: u64) -> anyhow::Result<u64> {
286+
let provider = Self::provider();
287+
288+
for _ in 0..count {
289+
provider
290+
.evm_mine(None)
291+
.await
292+
.map_err(|e| anyhow::anyhow!("Failed to mine block: {}", e))?;
293+
}
294+
295+
let block = provider
296+
.get_block_number()
297+
.await
298+
.map_err(|e| anyhow::anyhow!("Failed to get block number: {}", e))?;
299+
300+
Ok(block)
301+
}
302+
303+
/// Ensure the blockchain has reached at least the specified block number.
304+
/// Mines empty blocks if needed.
305+
pub async fn ensure_block(target_block: u64) -> anyhow::Result<()> {
306+
let provider = Self::provider();
307+
let current = provider
308+
.get_block_number()
309+
.await
310+
.map_err(|e| anyhow::anyhow!("Failed to get block number: {}", e))?;
311+
312+
if current < target_block {
313+
let blocks_needed = target_block - current;
314+
Self::mine_blocks(blocks_needed).await?;
315+
}
316+
317+
Ok(())
318+
}
283319
}

tests/tests/integration_tests.rs

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use std::collections::HashMap;
1313
use std::future::Future;
1414
use std::pin::Pin;
15-
use std::time::{self, Duration, Instant};
15+
use std::time::{Duration, Instant};
1616

1717
use anyhow::{anyhow, bail, Context, Result};
1818
use graph::components::subgraph::{
@@ -1388,24 +1388,6 @@ async fn test_declared_calls_struct_fields(ctx: TestContext) -> anyhow::Result<(
13881388
Ok(())
13891389
}
13901390

1391-
async fn wait_for_blockchain_block(block_number: i32) -> bool {
1392-
// Wait up to 5 minutes for the expected block to appear
1393-
const STATUS_WAIT: Duration = Duration::from_secs(300);
1394-
const REQUEST_REPEATING: Duration = time::Duration::from_secs(1);
1395-
let start = Instant::now();
1396-
while start.elapsed() < STATUS_WAIT {
1397-
let latest_block = Contract::latest_block().await;
1398-
if let Some(latest_block) = latest_block {
1399-
let number = latest_block.header.number;
1400-
if number >= block_number as u64 {
1401-
return true;
1402-
}
1403-
}
1404-
tokio::time::sleep(REQUEST_REPEATING).await;
1405-
}
1406-
false
1407-
}
1408-
14091391
/// The main test entrypoint.
14101392
#[graph::test]
14111393
async fn integration_tests() -> anyhow::Result<()> {
@@ -1452,10 +1434,17 @@ async fn integration_tests() -> anyhow::Result<()> {
14521434
cases
14531435
};
14541436

1455-
// Here we wait for a block in the blockchain in order not to influence
1456-
// block hashes for all the blocks until the end of the grafting tests.
1457-
// Currently the last used block for grafting test is the block 3.
1458-
assert!(wait_for_blockchain_block(SUBGRAPH_LAST_GRAFTING_BLOCK).await);
1437+
// Mine empty blocks to reach the required block number for grafting tests.
1438+
// This ensures deterministic block hashes for blocks 1-3 before any
1439+
// contract deployments occur.
1440+
status!(
1441+
"setup",
1442+
"Mining blocks to reach block {}",
1443+
SUBGRAPH_LAST_GRAFTING_BLOCK
1444+
);
1445+
Contract::ensure_block(SUBGRAPH_LAST_GRAFTING_BLOCK as u64)
1446+
.await
1447+
.context("Failed to mine initial blocks for grafting test")?;
14591448

14601449
let contracts = Contract::deploy_all().await?;
14611450

0 commit comments

Comments
 (0)