Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

try-runtime-cli: execute-block & create-snapshot tests #14343

Merged
merged 24 commits into from
Jun 24, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4bb74f2
execute-block test
Szegoo Jun 11, 2023
cb9720c
test create-snapshot
Szegoo Jun 12, 2023
2644c25
oops
Szegoo Jun 12, 2023
64ed955
Update utils/frame/try-runtime/cli/tests/create_snapshot.rs
Szegoo Jun 15, 2023
aa7e6a7
Update utils/frame/try-runtime/cli/tests/create_snapshot.rs
Szegoo Jun 15, 2023
2989dfc
Update utils/frame/try-runtime/cli/tests/create_snapshot.rs
Szegoo Jun 15, 2023
af1cfde
remove snapshot
Szegoo Jun 15, 2023
c1d5b80
execute block: new log
Szegoo Jun 15, 2023
c3a964d
use prefix & make tempfile a dev dependencie
Szegoo Jun 15, 2023
e7a54ab
Update utils/frame/try-runtime/cli/tests/execute_block.rs
Szegoo Jun 16, 2023
d3a9ca9
Update utils/frame/try-runtime/cli/tests/create_snapshot.rs
Szegoo Jun 16, 2023
6ce396e
".git/.scripts/commands/fmt/fmt.sh"
Jun 16, 2023
7d274e6
Merge remote-tracking branch 'origin/master' into try-runtime-tests
Jun 17, 2023
f439f28
--at option in execute-block test
Szegoo Jun 17, 2023
84a27de
fixes & use --at option in create-snapshot test
Szegoo Jun 17, 2023
7581859
hmm
Szegoo Jun 17, 2023
8fc182a
fmt
Szegoo Jun 17, 2023
b7c157b
remove nonsense
Szegoo Jun 18, 2023
f1c77b4
Update utils/frame/try-runtime/cli/tests/create_snapshot.rs
Szegoo Jun 21, 2023
08b881c
Update utils/frame/try-runtime/cli/tests/execute_block.rs
Szegoo Jun 21, 2023
e78e7e4
remove unnecessary test modules
Szegoo Jun 21, 2023
4e3e29b
try to load snapshot file
Szegoo Jun 21, 2023
2c689d5
Merge branch 'paritytech:master' into try-runtime-tests
Szegoo Jun 21, 2023
daab1cc
fix
Szegoo Jun 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions frame/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,12 @@ where
);
}

frame_support::log::info!(
target: LOG_TARGET,
"try-runtime: Block #{:?} successfully executed",
Copy link
Member

@ggwpez ggwpez Jun 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some ideas, we could do stuff here like:

  • State trace (output of all modified storage keys)
  • Print all executed calls + Events
  • Consumed weight
  • Block size etc

Probably most of it in JSON, so we can render it eventually (like chopsticks already does for state changes).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be done in this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Just some ideas for the future 😄

header.number(),
);

Ok(frame_system::Pallet::<System>::block_weight().total())
}

Expand Down
1 change: 1 addition & 0 deletions test-utils/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
substrate-rpc-client = { path = "../../utils/frame/rpc/client" }
sp-rpc = { version = "6.0.0", path = "../../primitives/rpc" }
assert_cmd = "2.0.10"
nix = "0.26.2"
regex = "1.7.3"
Expand Down
23 changes: 22 additions & 1 deletion test-utils/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use nix::{
};
use node_primitives::{Hash, Header};
use regex::Regex;
use sp_rpc::{list::ListOrValue, number::NumberOrHex};
use std::{
env,
io::{BufRead, BufReader, Read},
Expand Down Expand Up @@ -177,7 +178,8 @@ pub async fn wait_n_finalized_blocks(n: usize, url: &str) {
use substrate_rpc_client::{ws_client, ChainApi};

let mut built_blocks = std::collections::HashSet::new();
let mut interval = tokio::time::interval(Duration::from_secs(2));
let block_duration = Duration::from_secs(2);
let mut interval = tokio::time::interval(block_duration);
let rpc = ws_client(url).await.unwrap();

loop {
Expand Down Expand Up @@ -220,6 +222,25 @@ pub async fn run_node_for_a_while(base_path: &Path, args: &[&str]) {
.await
}

pub async fn block_hash(block_number: u64, url: &str) -> Result<Hash, String> {
use substrate_rpc_client::{ws_client, ChainApi};

let rpc = ws_client(url).await.unwrap();

let result = ChainApi::<(), Hash, Header, ()>::block_hash(
&rpc,
Some(ListOrValue::Value(NumberOrHex::Number(block_number.saturating_sub(1)))),
)
Szegoo marked this conversation as resolved.
Show resolved Hide resolved
.await
.map_err(|_| "Couldn't get block hash".to_string())?;

match result {
ListOrValue::Value(maybe_block_hash) if maybe_block_hash.is_some() =>
Ok(maybe_block_hash.unwrap()),
_ => Err("Couldn't get block hash".to_string()),
}
}

pub struct KillChildOnDrop(pub Child);

impl KillChildOnDrop {
Expand Down
2 changes: 2 additions & 0 deletions utils/frame/try-runtime/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ zstd = { version = "0.12.3", default-features = false }

[dev-dependencies]
assert_cmd = "2.0.10"
node-primitives = { path = "../../../../bin/node/primitives" }
regex = "1.7.3"
substrate-cli-test-utils = { path = "../../../../test-utils/cli" }
tempfile = "3.1.0"
tokio = "1.27.0"

[features]
Expand Down
82 changes: 82 additions & 0 deletions utils/frame/try-runtime/cli/tests/create_snapshot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#![cfg(unix)]
#[cfg(feature = "try-runtime")]
mod tests {
Szegoo marked this conversation as resolved.
Show resolved Hide resolved
use assert_cmd::cargo::cargo_bin;
use node_primitives::Hash;
use regex::Regex;
use std::{
path::{Path, PathBuf},
process,
time::Duration,
};
use substrate_cli_test_utils as common;
use tokio::process::{Child, Command};

#[tokio::test]
async fn create_snapshot_works() {
// Build substrate so binaries used in the test use the latest code.
common::build_substrate(&["--features=try-runtime"]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now understood why we have to build again. Just very annoying and slow…
Maybe we can somehow inherit the build args in this function, so that it re-uses the cargo cache.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be great. It does take quite some time to run all of these tests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea that would be a follow up as well; debug that build_substrate function and check if we can make it re-use the already existing build artifacts by using the same compile args that were used for the test.


let temp_dir = tempfile::Builder::new()
.prefix("try-runtime-cli-test-dir")
.tempdir()
.expect("Failed to create a tempdir");
let snap_file_path = temp_dir.path().join("snapshot.snap");

common::run_with_timeout(Duration::from_secs(60), async move {
fn create_snapshot(ws_url: &str, snap_file: &PathBuf, at: Hash) -> Child {
Command::new(cargo_bin("substrate"))
.stdout(process::Stdio::piped())
.stderr(process::Stdio::piped())
.args(&["try-runtime", "--runtime=existing"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, the need for --runtime for this subcommand was a fundamental mistake that I added at some point @liamaharon 🙈

Copy link
Contributor

@liamaharon liamaharon Jun 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wdyt about existing always being a default?

.args(&["create-snapshot", format!("--uri={}", ws_url).as_str()])
.arg(snap_file)
.args(&["--at", format!("{:?}", at).as_str()])
.kill_on_drop(true)
.spawn()
.unwrap()
}

// Start a node and wait for it to begin finalizing blocks
let mut node = common::KillChildOnDrop(common::start_node());
let ws_url = common::extract_info_from_output(node.stderr.take().unwrap()).0.ws_url;
common::wait_n_finalized_blocks(3, &ws_url).await;

let block_number = 2;
let block_hash = common::block_hash(block_number, &ws_url).await.unwrap();

// Try to create a snapshot.
let mut snapshot_creation = create_snapshot(&ws_url, &snap_file_path, block_hash);

let re = Regex::new(r#".*writing snapshot of (\d+) bytes to .*"#).unwrap();
let matched =
common::wait_for_stream_pattern_match(snapshot_creation.stderr.take().unwrap(), re)
.await;

// Assert that the snapshot creation succeded.
assert!(matched.is_ok(), "Failed to create snapshot");

let snapshot_is_on_disk = Path::new(&snap_file_path).exists();
Szegoo marked this conversation as resolved.
Show resolved Hide resolved
assert!(snapshot_is_on_disk, "Snapshot was not written to disk");
Szegoo marked this conversation as resolved.
Show resolved Hide resolved
})
.await;
}
}
70 changes: 70 additions & 0 deletions utils/frame/try-runtime/cli/tests/execute_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#![cfg(unix)]
#[cfg(feature = "try-runtime")]
mod tests {
Szegoo marked this conversation as resolved.
Show resolved Hide resolved
use assert_cmd::cargo::cargo_bin;
use node_primitives::Hash;
use regex::Regex;
use std::{process, time::Duration};
use substrate_cli_test_utils as common;
use tokio::process::{Child, Command};

#[tokio::test]
async fn block_execution_works() {
// Build substrate so binaries used in the test use the latest code.
common::build_substrate(&["--features=try-runtime"]);

common::run_with_timeout(Duration::from_secs(60), async move {
fn execute_block(ws_url: &str, at: Hash) -> Child {
Command::new(cargo_bin("substrate"))
.stdout(process::Stdio::piped())
.stderr(process::Stdio::piped())
.args(&["try-runtime", "--runtime=existing"])
.args(&["execute-block"])
.args(&["live", format!("--uri={}", ws_url).as_str()])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will only execute the latest block. Would be interesting if you also think about incorporating --at, if reasonably possible.

Same applies to the other one as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I will do that.

.args(&["--at", format!("{:?}", at).as_str()])
.kill_on_drop(true)
.spawn()
.unwrap()
}

// Start a node and wait for it to begin finalizing blocks
let mut node = common::KillChildOnDrop(common::start_node());
let ws_url = common::extract_info_from_output(node.stderr.take().unwrap()).0.ws_url;
common::wait_n_finalized_blocks(3, &ws_url).await;

let block_number = 1;
let block_hash = common::block_hash(block_number, &ws_url).await.unwrap();

// Try to execute the block.
let mut block_execution = execute_block(&ws_url, block_hash);

let expected_output = format!(r#".*Block #{} successfully executed"#, block_number);
let re = Regex::new(expected_output.as_str()).unwrap();
let matched =
common::wait_for_stream_pattern_match(block_execution.stderr.take().unwrap(), re)
.await;

// Assert that the block-execution process has executed a block.
assert!(matched.is_ok());
})
.await;
}
}
2 changes: 1 addition & 1 deletion utils/frame/try-runtime/cli/tests/follow_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ mod tests {
common::wait_for_stream_pattern_match(follow.stderr.take().unwrap(), re).await;

// Assert that the follow-chain process has followed at least 3 blocks.
assert!(matches!(matched, Ok(_)));
assert!(matched.is_ok());
Szegoo marked this conversation as resolved.
Show resolved Hide resolved
})
.await;
}
Expand Down