Skip to content

Commit a9bdaa3

Browse files
committed
tests: Add integration tests for gnd
1 parent 039a522 commit a9bdaa3

File tree

4 files changed

+324
-47
lines changed

4 files changed

+324
-47
lines changed

tests/src/config.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::sync::OnceLock;
12
use std::time::{Duration, Instant};
23
use std::{fs, path::PathBuf};
34

@@ -13,6 +14,15 @@ use crate::status;
1314

1415
lazy_static! {
1516
pub static ref CONFIG: Config = Config::default();
17+
static ref DEV_MODE: OnceLock<bool> = OnceLock::new();
18+
}
19+
20+
pub fn set_dev_mode(val: bool) {
21+
DEV_MODE.set(val).expect("DEV_MODE already set");
22+
}
23+
24+
pub fn dev_mode() -> bool {
25+
*DEV_MODE.get().unwrap_or(&false)
1626
}
1727

1828
#[derive(Clone, Debug)]
@@ -117,6 +127,26 @@ impl GraphNodeConfig {
117127
}
118128
}
119129
}
130+
131+
pub fn from_env() -> Self {
132+
if dev_mode() {
133+
Self::gnd()
134+
} else {
135+
Self::default()
136+
}
137+
}
138+
139+
fn gnd() -> Self {
140+
let bin = fs::canonicalize("../target/debug/gnd")
141+
.expect("failed to infer `graph-node` program location. (Was it built already?)");
142+
143+
Self {
144+
bin,
145+
ports: GraphNodePorts::default(),
146+
ipfs_uri: "http://localhost:3001".to_string(),
147+
log_file: TestFile::new("integration-tests/graph-node.log"),
148+
}
149+
}
120150
}
121151

122152
impl Default for GraphNodeConfig {
@@ -145,6 +175,13 @@ pub struct Config {
145175

146176
impl Config {
147177
pub async fn spawn_graph_node(&self) -> anyhow::Result<Child> {
178+
self.spawn_graph_node_with_args(&[]).await
179+
}
180+
181+
pub async fn spawn_graph_node_with_args(
182+
&self,
183+
additional_args: &[&str],
184+
) -> anyhow::Result<Child> {
148185
let ports = &self.graph_node.ports;
149186

150187
let args = [
@@ -163,6 +200,12 @@ impl Config {
163200
"--metrics-port",
164201
&ports.metrics.to_string(),
165202
];
203+
204+
let args = args
205+
.iter()
206+
.chain(additional_args.iter())
207+
.cloned()
208+
.collect::<Vec<_>>();
166209
let stdout = self.graph_node.log_file.create();
167210
let stderr = stdout.try_clone()?;
168211
status!(
@@ -174,7 +217,7 @@ impl Config {
174217
command
175218
.stdout(stdout)
176219
.stderr(stderr)
177-
.args(args)
220+
.args(args.clone())
178221
.env("GRAPH_STORE_WRITE_BATCH_DURATION", "5")
179222
.env("ETHEREUM_REORG_THRESHOLD", "0");
180223

@@ -254,7 +297,7 @@ impl Default for Config {
254297
port: 3021,
255298
host: "localhost".to_string(),
256299
},
257-
graph_node: GraphNodeConfig::default(),
300+
graph_node: GraphNodeConfig::from_env(),
258301
graph_cli,
259302
num_parallel_tests,
260303
timeout: Duration::from_secs(600),

tests/src/subgraph.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ impl Subgraph {
4747
Ok(())
4848
}
4949

50-
/// Deploy the subgraph by running the required `graph` commands
51-
pub async fn deploy(name: &str, contracts: &[Contract]) -> anyhow::Result<String> {
50+
/// Prepare the subgraph for deployment by patching contracts and checking for subgraph datasources
51+
pub async fn prepare(
52+
name: &str,
53+
contracts: &[Contract],
54+
) -> anyhow::Result<(TestFile, String, bool)> {
5255
let dir = Self::dir(name);
5356
let name = format!("test/{name}");
5457

@@ -62,6 +65,13 @@ impl Subgraph {
6265
.and_then(|ds| ds.iter().find(|d| d["kind"].as_str() == Some("subgraph")))
6366
.is_some();
6467

68+
Ok((dir, name, has_subgraph_datasource))
69+
}
70+
71+
/// Deploy the subgraph by running the required `graph` commands
72+
pub async fn deploy(name: &str, contracts: &[Contract]) -> anyhow::Result<String> {
73+
let (dir, name, has_subgraph_datasource) = Self::prepare(name, contracts).await?;
74+
6575
// graph codegen subgraph.yaml
6676
let mut prog = Command::new(&CONFIG.graph_cli);
6777
let mut cmd = prog.arg("codegen").arg("subgraph.yaml.patched");

tests/tests/gnd_tests.rs

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
use anyhow::anyhow;
2+
use graph::futures03::StreamExt;
3+
use graph_tests::config::set_dev_mode;
4+
use graph_tests::contract::Contract;
5+
use graph_tests::subgraph::Subgraph;
6+
use graph_tests::{error, status, CONFIG};
7+
8+
mod integration_tests;
9+
10+
use integration_tests::{
11+
stop_graph_node, subgraph_data_sources, test_block_handlers,
12+
test_multiple_subgraph_datasources, yarn_workspace, TestCase, TestResult,
13+
};
14+
15+
/// The main test entrypoint.
16+
#[tokio::test]
17+
async fn gnd_tests() -> anyhow::Result<()> {
18+
set_dev_mode(true);
19+
20+
let test_name_to_run = std::env::var("TEST_CASE").ok();
21+
22+
let cases = vec![
23+
TestCase::new("block-handlers", test_block_handlers),
24+
TestCase::new_with_source_subgraphs(
25+
"subgraph-data-sources",
26+
subgraph_data_sources,
27+
vec!["QmWi3H11QFE2PiWx6WcQkZYZdA5UasaBptUJqGn54MFux5:source-subgraph"],
28+
),
29+
TestCase::new_with_source_subgraphs(
30+
"multiple-subgraph-datasources",
31+
test_multiple_subgraph_datasources,
32+
vec![
33+
"QmYHp1bPEf7EoYBpEtJUpZv1uQHYQfWE4AhvR6frjB1Huj:source-subgraph-a",
34+
"QmYBEzastJi7bsa722ac78tnZa6xNnV9vvweerY4kVyJtq:source-subgraph-b",
35+
],
36+
),
37+
];
38+
39+
// Filter the test cases if a specific test name is provided
40+
let cases_to_run: Vec<_> = if let Some(test_name) = test_name_to_run {
41+
cases
42+
.into_iter()
43+
.filter(|case| case.name == test_name)
44+
.collect()
45+
} else {
46+
cases
47+
};
48+
49+
let contracts = Contract::deploy_all().await?;
50+
51+
status!("setup", "Resetting database");
52+
CONFIG.reset_database();
53+
54+
status!("setup", "Initializing yarn workspace");
55+
yarn_workspace().await?;
56+
57+
for i in cases_to_run.iter() {
58+
i.prepare(&contracts).await?;
59+
}
60+
status!("setup", "Prepared all cases");
61+
62+
let manifests = cases_to_run
63+
.iter()
64+
.map(|case| {
65+
Subgraph::dir(&case.name)
66+
.path
67+
.join("subgraph.yaml")
68+
.to_str()
69+
.unwrap()
70+
.to_string()
71+
})
72+
.collect::<Vec<_>>()
73+
.join(",");
74+
75+
let aliases = cases_to_run
76+
.iter()
77+
.filter_map(|case| case.source_subgraph.as_ref())
78+
.flatten()
79+
.filter_map(|source_subgraph| {
80+
source_subgraph.alias().map(|alias| {
81+
let manifest_path = Subgraph::dir(source_subgraph.test_name())
82+
.path
83+
.join("subgraph.yaml")
84+
.to_str()
85+
.unwrap()
86+
.to_string();
87+
format!("{}:{}", alias, manifest_path)
88+
})
89+
})
90+
.collect::<Vec<_>>();
91+
92+
let aliases_str = aliases.join(",");
93+
let args = if aliases.is_empty() {
94+
vec!["--manifests", &manifests]
95+
} else {
96+
vec!["--manifests", &manifests, "--sources", &aliases_str]
97+
};
98+
99+
// Spawn graph-node.
100+
status!("graph-node", "Starting graph-node");
101+
102+
let mut graph_node_child_command = CONFIG.spawn_graph_node_with_args(&args).await?;
103+
104+
let num_sources = aliases.len();
105+
106+
let stream = tokio_stream::iter(cases_to_run)
107+
.enumerate()
108+
.map(|(index, case)| {
109+
let subgraph_name = format!("subgraph-{}", num_sources + index);
110+
case.check_health_and_test(&contracts, subgraph_name)
111+
})
112+
.buffered(CONFIG.num_parallel_tests);
113+
114+
let mut results: Vec<TestResult> = stream.collect::<Vec<_>>().await;
115+
results.sort_by_key(|result| result.name.clone());
116+
117+
// Stop graph-node and read its output.
118+
let graph_node_res = stop_graph_node(&mut graph_node_child_command).await;
119+
120+
status!(
121+
"graph-node",
122+
"graph-node logs are in {}",
123+
CONFIG.graph_node.log_file.path.display()
124+
);
125+
126+
match graph_node_res {
127+
Ok(_) => {
128+
status!("graph-node", "Stopped graph-node");
129+
}
130+
Err(e) => {
131+
error!("graph-node", "Failed to stop graph-node: {}", e);
132+
}
133+
}
134+
135+
println!("\n\n{:=<60}", "");
136+
println!("Test results:");
137+
println!("{:-<60}", "");
138+
for result in &results {
139+
result.print();
140+
}
141+
println!("\n");
142+
143+
if results.iter().any(|result| !result.success()) {
144+
Err(anyhow!("Some tests failed"))
145+
} else {
146+
Ok(())
147+
}
148+
}

0 commit comments

Comments
 (0)