Skip to content

Commit 0aa8950

Browse files
committed
tests: Mock arweave resolver to fix flaky arweave_file_data_sources test
The test relied on real HTTP calls to arweave.net and a 1500ms sleep hack to work around the resulting race condition. Replace with a StaticArweaveResolver that returns synthetic content from memory, making the test deterministic and faster. Also generalize arweave_service() to accept Arc<dyn ArweaveResolver> instead of Arc<ArweaveClient>, and ensure setup_inner uses a single resolver instance for both the polling service and TestContext.
1 parent 629f2f7 commit 0aa8950

File tree

3 files changed

+78
-24
lines changed

3 files changed

+78
-24
lines changed

core/src/polling_monitor/arweave_service.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use anyhow::Error;
22
use bytes::Bytes;
33
use graph::futures03::future::BoxFuture;
44
use graph::{
5-
components::link_resolver::{ArweaveClient, ArweaveResolver, FileSizeLimit},
5+
components::link_resolver::{ArweaveResolver, FileSizeLimit},
66
data_source::offchain::Base64,
77
derive::CheapClone,
88
prelude::CheapClone,
@@ -13,7 +13,7 @@ use tower::{buffer::Buffer, ServiceBuilder, ServiceExt};
1313
pub type ArweaveService = Buffer<Base64, BoxFuture<'static, Result<Option<Bytes>, Error>>>;
1414

1515
pub fn arweave_service(
16-
client: Arc<ArweaveClient>,
16+
client: Arc<dyn ArweaveResolver>,
1717
rate_limit: u16,
1818
max_file_size: FileSizeLimit,
1919
) -> ArweaveService {
@@ -34,7 +34,7 @@ pub fn arweave_service(
3434

3535
#[derive(Clone, CheapClone)]
3636
struct ArweaveServiceInner {
37-
client: Arc<ArweaveClient>,
37+
client: Arc<dyn ArweaveResolver>,
3838
max_file_size: FileSizeLimit,
3939
}
4040

tests/src/fixture/mod.rs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use graph::blockchain::{
2020
};
2121
use graph::cheap_clone::CheapClone;
2222
use graph::components::link_resolver::{
23-
ArweaveClient, ArweaveResolver, FileLinkResolver, FileSizeLimit, LinkResolverContext,
23+
ArweaveClient, ArweaveClientError, ArweaveResolver, FileLinkResolver, FileSizeLimit,
24+
LinkResolverContext,
2425
};
2526
use graph::components::metrics::MetricsRegistry;
2627
use graph::components::network_provider::ChainName;
@@ -422,14 +423,46 @@ pub struct TestInfo {
422423
pub hash: DeploymentHash,
423424
}
424425

426+
#[derive(Debug)]
427+
pub struct StaticArweaveResolver {
428+
content: HashMap<String, Vec<u8>>,
429+
}
430+
431+
impl StaticArweaveResolver {
432+
pub fn new(content: HashMap<String, Vec<u8>>) -> Self {
433+
Self { content }
434+
}
435+
}
436+
437+
#[async_trait]
438+
impl ArweaveResolver for StaticArweaveResolver {
439+
async fn get(
440+
&self,
441+
file: &graph::data_source::offchain::Base64,
442+
) -> Result<Vec<u8>, ArweaveClientError> {
443+
self.get_with_limit(file, &FileSizeLimit::Unlimited).await
444+
}
445+
446+
async fn get_with_limit(
447+
&self,
448+
file: &graph::data_source::offchain::Base64,
449+
_limit: &FileSizeLimit,
450+
) -> Result<Vec<u8>, ArweaveClientError> {
451+
self.content
452+
.get(file.as_str())
453+
.cloned()
454+
.ok_or(ArweaveClientError::UnableToCheckFileSize)
455+
}
456+
}
457+
425458
pub async fn setup<C: Blockchain>(
426459
test_info: &TestInfo,
427460
stores: &Stores,
428461
chain: &impl TestChainTrait<C>,
429462
graft_block: Option<BlockPtr>,
430463
env_vars: Option<EnvVars>,
431464
) -> TestContext {
432-
setup_inner(test_info, stores, chain, graft_block, env_vars, None).await
465+
setup_inner(test_info, stores, chain, graft_block, env_vars, None, None).await
433466
}
434467

435468
pub async fn setup_with_file_link_resolver<C: Blockchain>(
@@ -449,6 +482,27 @@ pub async fn setup_with_file_link_resolver<C: Blockchain>(
449482
graft_block,
450483
env_vars,
451484
Some(link_resolver),
485+
None,
486+
)
487+
.await
488+
}
489+
490+
pub async fn setup_with_arweave_resolver<C: Blockchain>(
491+
test_info: &TestInfo,
492+
stores: &Stores,
493+
chain: &impl TestChainTrait<C>,
494+
graft_block: Option<BlockPtr>,
495+
env_vars: Option<EnvVars>,
496+
arweave_resolver: Arc<dyn ArweaveResolver>,
497+
) -> TestContext {
498+
setup_inner(
499+
test_info,
500+
stores,
501+
chain,
502+
graft_block,
503+
env_vars,
504+
None,
505+
Some(arweave_resolver),
452506
)
453507
.await
454508
}
@@ -460,6 +514,7 @@ pub async fn setup_inner<C: Blockchain>(
460514
graft_block: Option<BlockPtr>,
461515
env_vars: Option<EnvVars>,
462516
link_resolver: Option<Arc<dyn LinkResolver>>,
517+
arweave_resolver: Option<Arc<dyn ArweaveResolver>>,
463518
) -> TestContext {
464519
let env_vars = Arc::new(match env_vars {
465520
Some(ev) => ev,
@@ -506,7 +561,8 @@ pub async fn setup_inner<C: Blockchain>(
506561
env_vars.mappings.ipfs_request_limit,
507562
);
508563

509-
let arweave_resolver = Arc::new(ArweaveClient::default());
564+
let arweave_resolver: Arc<dyn ArweaveResolver> =
565+
arweave_resolver.unwrap_or_else(|| Arc::new(ArweaveClient::default()));
510566
let arweave_service = arweave_service(
511567
arweave_resolver.cheap_clone(),
512568
env_vars.mappings.ipfs_request_limit,
@@ -603,8 +659,6 @@ pub async fn setup_inner<C: Blockchain>(
603659
.await
604660
.expect("failed to create subgraph version");
605661

606-
let arweave_resolver = Arc::new(ArweaveClient::default());
607-
608662
TestContext {
609663
logger: logger_factory.subgraph_logger(&deployment),
610664
provider: subgraph_provider,

tests/tests/runner_tests.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashMap;
12
use std::marker::PhantomData;
23
use std::str::FromStr;
34
use std::sync::atomic::{self, AtomicBool};
@@ -23,8 +24,8 @@ use graph_tests::fixture::ethereum::{
2324
};
2425

2526
use graph_tests::fixture::{
26-
self, test_ptr, test_ptr_reorged, MockAdapterSelector, NoopAdapterSelector, TestChainTrait,
27-
TestContext, TestInfo,
27+
self, test_ptr, test_ptr_reorged, MockAdapterSelector, NoopAdapterSelector,
28+
StaticArweaveResolver, TestChainTrait, TestContext, TestInfo,
2829
};
2930
use graph_tests::recipe::{build_subgraph_with_pnpm_cmd_and_arg, RunnerTestRecipe};
3031
use slog::{o, Discard, Logger};
@@ -1141,23 +1142,22 @@ async fn arweave_file_data_sources() {
11411142
// HASH used in the mappings.
11421143
let id = "8APeQ5lW0-csTcBaGdPBDLAL2ci2AT9pTn2tppGPU_8";
11431144

1144-
// This test assumes the file data sources will be processed in the same block in which they are
1145-
// created. But the test might fail due to a race condition if for some reason it takes longer
1146-
// than expected to fetch the file from arweave. The sleep here will conveniently happen after the
1147-
// data source is added to the offchain monitor but before the monitor is checked, in an an
1148-
// attempt to ensure the monitor has enough time to fetch the file.
1149-
let adapter_selector = NoopAdapterSelector {
1150-
x: PhantomData,
1151-
triggers_in_block_sleep: Duration::from_millis(1500),
1152-
};
1153-
let chain = chain(
1154-
&test_info.test_name,
1155-
blocks.clone(),
1145+
// Use a mock arweave resolver to avoid real network calls and eliminate the
1146+
// race condition that caused this test to be flaky.
1147+
let arweave_content: HashMap<String, Vec<u8>> =
1148+
HashMap::from([(id.to_string(), b"test arweave content".to_vec())]);
1149+
let arweave_resolver = Arc::new(StaticArweaveResolver::new(arweave_content));
1150+
1151+
let chain = chain(&test_info.test_name, blocks.clone(), &stores, None).await;
1152+
let ctx = fixture::setup_with_arweave_resolver(
1153+
&test_info,
11561154
&stores,
1157-
Some(Arc::new(adapter_selector)),
1155+
&chain,
1156+
None,
1157+
None,
1158+
arweave_resolver,
11581159
)
11591160
.await;
1160-
let ctx = fixture::setup(&test_info, &stores, &chain, None, None).await;
11611161
ctx.start_and_sync_to(test_ptr(2)).await;
11621162

11631163
let store = ctx.store.cheap_clone();

0 commit comments

Comments
 (0)