Skip to content

Commit 478132e

Browse files
committed
adding runner_test for auto-graft-sync
1 parent 6302611 commit 478132e

File tree

9 files changed

+348
-6
lines changed

9 files changed

+348
-6
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[
2+
{
3+
"inputs": [],
4+
"stateMutability": "nonpayable",
5+
"type": "constructor"
6+
},
7+
{
8+
"anonymous": false,
9+
"inputs": [
10+
{
11+
"indexed": false,
12+
"internalType": "uint16",
13+
"name": "x",
14+
"type": "uint16"
15+
}
16+
],
17+
"name": "Trigger",
18+
"type": "event"
19+
},
20+
{
21+
"inputs": [
22+
{
23+
"internalType": "uint16",
24+
"name": "x",
25+
"type": "uint16"
26+
}
27+
],
28+
"name": "emitTrigger",
29+
"outputs": [],
30+
"stateMutability": "nonpayable",
31+
"type": "function"
32+
}
33+
]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[general]
2+
3+
# This is the config flag for enabling auto-graft-sync, which is the target of this test.
4+
auto_graft_sync = true
5+
6+
[store]
7+
[store.primary]
8+
connection = "$THEGRAPH_STORE_POSTGRES_DIESEL_URL"
9+
pool_size = 10
10+
11+
[deployment]
12+
[[deployment.rule]]
13+
store = "primary"
14+
indexers = ["default"]
15+
16+
[chains]
17+
ingestor = "default"
18+
19+
# The tests do not talk to ethereum clients
20+
[chains.test]
21+
shard = "primary"
22+
provider = [{ label = "penguin", url = "http://localhost:1/", features = [] }]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
const fs = require('fs');
3+
const { execSync } = require('child_process');
4+
5+
// This takes a subgraphName, outPath, and Qm.. hash as a CLI input, which is the graft base.
6+
const outPath = process.argv[2];
7+
const graftBase = process.argv[3];
8+
9+
const yamlPath = './template.yaml';
10+
let yamlContent = fs.readFileSync(yamlPath, 'utf-8');
11+
yamlContent = yamlContent.replace(/base: .+/, `base: ${graftBase}`);
12+
fs.writeFileSync(outPath, yamlContent);
13+
console.log("fuzzba")
14+
15+
// Assuming you have your IPFS_URI exported as environment variables.
16+
// Instead of deploy, run graph build to -only upload to ipfs-.
17+
execSync('graph build ' + outPath + ' --ipfs $IPFS_URI', {
18+
stdio: 'inherit'
19+
});
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# for this test, this is the lowest level of the grafting hierarchy
2+
specVersion: 0.0.4
3+
features:
4+
- grafting
5+
schema:
6+
file: ./schema.graphql
7+
dataSources:
8+
- kind: ethereum/contract
9+
name: Contract
10+
network: test
11+
source:
12+
address: "0xCfEB869F69431e42cdB54A4F4f105C19C080A601"
13+
abi: Contract
14+
mapping:
15+
kind: ethereum/events
16+
apiVersion: 0.0.6
17+
language: wasm/assemblyscript
18+
entities:
19+
- Gravatar
20+
abis:
21+
- name: Contract
22+
file: ./abis/Contract.abi
23+
blockHandlers:
24+
- handler: handleBlock
25+
file: ./src/mapping.ts
26+
# Tests that adding a data source is possible in a graft
27+
- kind: ethereum/contract
28+
name: Contract2
29+
network: test
30+
source:
31+
address: "0xCfEB869F69431e42cdB54A4F4f105C19C080A601"
32+
abi: Contract
33+
mapping:
34+
kind: ethereum/events
35+
apiVersion: 0.0.6
36+
language: wasm/assemblyscript
37+
entities:
38+
- Gravatar
39+
abis:
40+
- name: Contract
41+
file: ./abis/Contract.abi
42+
callHandlers:
43+
- handler: handleBlock
44+
function: emitTrigger(uint16)
45+
file: ./src/mapping.ts
46+
templates:
47+
- kind: ethereum/contract
48+
name: Template
49+
network: test
50+
source:
51+
abi: Contract
52+
mapping:
53+
kind: ethereum/events
54+
apiVersion: 0.0.6
55+
language: wasm/assemblyscript
56+
entities:
57+
- Gravatar
58+
abis:
59+
- name: Contract
60+
file: ./abis/Contract.abi
61+
blockHandlers:
62+
- handler: handleBlockTemplate
63+
file: ./src/mapping.ts
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "auto-graft-sync",
3+
"version": "0.1.0",
4+
"scripts": {
5+
"codegen": "graph codegen graft-base.yaml --skip-migrations",
6+
"build-graft-root": "graph build graft-base.yaml --ipfs $IPFS_URI",
7+
"build:test-auto-graft-sync": "node generateManifestFromTemplate.js"
8+
},
9+
"devDependencies": {
10+
"@graphprotocol/graph-cli": "0.60.0",
11+
"@graphprotocol/graph-ts": "0.31.0"
12+
}
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# The `id` is the block number and `count` the handler invocations at that block.
2+
type DataSourceCount @entity {
3+
id: ID!
4+
count: Int!
5+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {
2+
ethereum,
3+
DataSourceContext,
4+
dataSource,
5+
Address,
6+
BigInt,
7+
} from "@graphprotocol/graph-ts";
8+
import { Template } from "../generated/templates";
9+
import { DataSourceCount } from "../generated/schema";
10+
11+
export function handleBlock(block: ethereum.Block): void {
12+
let context = new DataSourceContext();
13+
context.setBigInt("number", block.number);
14+
context.setBytes("hash", block.hash);
15+
16+
Template.createWithContext(
17+
changetype<Address>(Address.fromHexString(
18+
"0x2E645469f354BB4F5c8a05B3b30A929361cf77eC"
19+
)),
20+
context
21+
);
22+
}
23+
24+
export function handleBlockTemplate(block: ethereum.Block): void {
25+
let count = DataSourceCount.load(block.number.toString());
26+
if (count == null) {
27+
count = new DataSourceCount(block.number.toString());
28+
count.count = 0;
29+
}
30+
31+
let ctx = dataSource.context();
32+
let number = ctx.getBigInt("number");
33+
assert(
34+
count.count == number.toI32(),
35+
"wrong count, found " + BigInt.fromI32(count.count).toString()
36+
);
37+
count.count += 1;
38+
count.save();
39+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
specVersion: 0.0.4
2+
features:
3+
- grafting
4+
schema:
5+
file: ./schema.graphql
6+
graft:
7+
# This value will be overwritten by the templates
8+
base: QmcAL39QSKZvRssr2ToCJrav7XK9ggajxvBR7M1NNUCqdh
9+
block: 3
10+
dataSources:
11+
- kind: ethereum/contract
12+
name: Contract
13+
network: test
14+
source:
15+
address: "0xCfEB869F69431e42cdB54A4F4f105C19C080A601"
16+
abi: Contract
17+
mapping:
18+
kind: ethereum/events
19+
apiVersion: 0.0.6
20+
language: wasm/assemblyscript
21+
entities:
22+
- Gravatar
23+
abis:
24+
- name: Contract
25+
file: ./abis/Contract.abi
26+
blockHandlers:
27+
- handler: handleBlock
28+
file: ./src/mapping.ts
29+
# Tests that adding a data source is possible in a graft
30+
- kind: ethereum/contract
31+
name: Contract2
32+
network: test
33+
source:
34+
address: "0xCfEB869F69431e42cdB54A4F4f105C19C080A601"
35+
abi: Contract
36+
mapping:
37+
kind: ethereum/events
38+
apiVersion: 0.0.6
39+
language: wasm/assemblyscript
40+
entities:
41+
- Gravatar
42+
abis:
43+
- name: Contract
44+
file: ./abis/Contract.abi
45+
callHandlers:
46+
- handler: handleBlock
47+
function: emitTrigger(uint16)
48+
file: ./src/mapping.ts
49+
templates:
50+
- kind: ethereum/contract
51+
name: Template
52+
network: test
53+
source:
54+
abi: Contract
55+
mapping:
56+
kind: ethereum/events
57+
apiVersion: 0.0.6
58+
language: wasm/assemblyscript
59+
entities:
60+
- Gravatar
61+
abis:
62+
- name: Contract
63+
file: ./abis/Contract.abi
64+
blockHandlers:
65+
- handler: handleBlockTemplate
66+
file: ./src/mapping.ts

tests/tests/runner_tests.rs

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,10 @@ async fn data_source_revert() -> anyhow::Result<()> {
143143

144144
// Test grafted version
145145
let subgraph_name = SubgraphName::new("data-source-revert-grafted").unwrap();
146-
let hash = build_subgraph_with_yarn_cmd_and_arg(
146+
let hash = build_subgraph_with_yarn_cmd_and_args(
147147
"./runner-tests/data-source-revert",
148148
"deploy:test-grafted",
149-
Some(&test_info.hash),
149+
vec![&test_info.hash],
150150
)
151151
.await;
152152
let test_info = TestInfo {
@@ -1261,20 +1261,102 @@ async fn arweave_file_data_sources() {
12611261
);
12621262
}
12631263

1264+
#[tokio::test]
1265+
async fn auto_graft_sync() -> anyhow::Result<()> {
1266+
let stores = fixture::stores(
1267+
"auto_graft_sync",
1268+
"./runner-tests/auto-graft-sync/config.toml",
1269+
)
1270+
.await;
1271+
1272+
let test_name = "auto_graft_sync";
1273+
1274+
let blocks = {
1275+
let block0 = genesis();
1276+
let block1 = empty_block(block0.ptr(), test_ptr(1));
1277+
let block1_reorged_ptr = BlockPtr {
1278+
number: 1,
1279+
hash: H256::from_low_u64_be(12).into(),
1280+
};
1281+
let block1_reorged = empty_block(block0.ptr(), block1_reorged_ptr.clone());
1282+
let block2 = empty_block(block1_reorged_ptr, test_ptr(2));
1283+
let block3 = empty_block(block2.ptr(), test_ptr(3));
1284+
let block4 = empty_block(block3.ptr(), test_ptr(4));
1285+
vec![block0, block1, block1_reorged, block2, block3, block4]
1286+
};
1287+
1288+
let chain = chain(&test_name, blocks.clone(), &stores, None).await;
1289+
1290+
// Root graft
1291+
// only build the subgraph and create it, but don't deploy it to be assigned
1292+
let root_deployment_hash = build_subgraph_with_yarn_cmd_and_args(
1293+
"./runner-tests/auto-graft-sync",
1294+
"build-graft-root",
1295+
vec![],
1296+
)
1297+
.await;
1298+
1299+
let mut prev_hash = root_deployment_hash.clone();
1300+
for i in (0..10).rev() {
1301+
let outfile = format!("auto-graft-sync-{}.yaml", i);
1302+
// Test grafted version
1303+
let hash = build_subgraph_with_yarn_cmd_and_args(
1304+
"./runner-tests/auto-graft-sync",
1305+
"build:test-auto-graft-sync",
1306+
vec![&outfile, &prev_hash],
1307+
)
1308+
.await;
1309+
prev_hash = hash;
1310+
}
1311+
1312+
let subgraph_name = SubgraphName::new("auto-graft-sync-tip".to_string()).unwrap();
1313+
let test_info = TestInfo {
1314+
test_name: test_name.to_string(),
1315+
hash: prev_hash.clone(),
1316+
test_dir: "./runner-tests/auto-graft-sync".to_string(),
1317+
subgraph_name,
1318+
};
1319+
1320+
let base_ctx = fixture::setup(&test_info, &stores, &chain, None, None).await;
1321+
1322+
let stop_block = test_ptr(3);
1323+
base_ctx.start_and_sync_to(stop_block).await;
1324+
1325+
let graft_block = Some(test_ptr(3));
1326+
let grafted_ctx = fixture::setup(&test_info, &stores, &chain, graft_block, None).await;
1327+
let stop_block = test_ptr(4);
1328+
grafted_ctx.start_and_sync_to(stop_block).await;
1329+
1330+
let query_res = grafted_ctx
1331+
.query(r#"{ dataSourceCount(id: "4") { id, count } }"#)
1332+
.await
1333+
.unwrap();
1334+
1335+
// TODO: The semantically correct value for `count` would be 5. But because the test fixture
1336+
// uses a `NoopTriggersAdapter` the data sources are not reprocessed in the block in which they
1337+
// are created.
1338+
assert_eq!(
1339+
query_res,
1340+
Some(object! { dataSourceCount: object!{ id: "4", count: 4 } })
1341+
);
1342+
1343+
Ok(())
1344+
}
1345+
12641346
/// deploy_cmd is the command to run to deploy the subgraph. If it is None, the
12651347
/// default `yarn deploy:test` is used.
12661348
async fn build_subgraph(dir: &str, deploy_cmd: Option<&str>) -> DeploymentHash {
12671349
build_subgraph_with_yarn_cmd(dir, deploy_cmd.unwrap_or("deploy:test")).await
12681350
}
12691351

12701352
async fn build_subgraph_with_yarn_cmd(dir: &str, yarn_cmd: &str) -> DeploymentHash {
1271-
build_subgraph_with_yarn_cmd_and_arg(dir, yarn_cmd, None).await
1353+
build_subgraph_with_yarn_cmd_and_args(dir, yarn_cmd, vec![]).await
12721354
}
12731355

1274-
async fn build_subgraph_with_yarn_cmd_and_arg(
1356+
async fn build_subgraph_with_yarn_cmd_and_args(
12751357
dir: &str,
12761358
yarn_cmd: &str,
1277-
arg: Option<&str>,
1359+
mut additional_args: Vec<&str>,
12781360
) -> DeploymentHash {
12791361
// Test that IPFS is up.
12801362
IpfsClient::localhost()
@@ -1296,7 +1378,7 @@ async fn build_subgraph_with_yarn_cmd_and_arg(
12961378
run_cmd(Command::new("yarn").arg("codegen").current_dir(dir));
12971379

12981380
let mut args = vec![yarn_cmd];
1299-
args.extend(arg);
1381+
args.append(&mut additional_args);
13001382

13011383
// Run `deploy` for the side effect of uploading to IPFS, the graph node url
13021384
// is fake and the actual deploy call is meant to fail.

0 commit comments

Comments
 (0)